12

I am trying to understand what the following means?

public class Bar<T extends Bar<T>> extends Foo<T> {
    //Some code
}

What is the advantage of doing something like this (e.g. use-case?).

student
  • 167
  • 1
  • 5

5 Answers5

7

That's a fairly theoretical example, but you could need it in this case:

public class Bar<T extends Bar<T>> extends Foo<T> {

    private final T value;

    public T getValue() { return value; }

    public void method(T param) {
        if (param.getValue().equals(someValue)) {
            doSomething();
        } else {
            doSomethingElse();
        }
    }
}

You would not be able to call param.getValue() if T were not a Bar, which it is because T extends Bar<T>.

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
assylias
  • 321,522
  • 82
  • 660
  • 783
  • @maba Looks like I changed my ming mid-way ;-) amended. – assylias Sep 04 '12 at 17:35
  • 2
    Note that `Bar` should be abstract because it could never be used directly. See my answer here: http://stackoverflow.com/questions/7354740/is-there-a-way-to-refer-to-the-current-type-with-a-type-variable/7355094#7355094 – Paul Bellora Sep 04 '12 at 19:39
  • 1
    @PaulBellora Indeed. `java.lang.Enum` has very similar definition: `public abstract class Enum> implements Comparable` – dcernahoschi Sep 04 '12 at 20:31
  • @dcernahoschi that would be a great answer. Just saw you made one. +1 for that. – assylias Sep 04 '12 at 20:59
  • @PaulBellora @dcernahoschi What about `static > Bar createBar() { return new Bar(); }`? – Ben Schulz Sep 05 '12 at 07:11
  • @BenSchulz It's not just about instantiating a `Bar` but statically typing it (e.g. assigning it to a variable). Just try it yourself - you'll quickly see that there's no way to use `Bar` directly because of its recursive type parameter (unless you revert to a raw type, which defeats the purpose of expressing `T`). You would need to declare `final class Baz extends Bar` and instantiate/statically type that for example. – Paul Bellora Sep 05 '12 at 13:57
  • @PaulBellora Why does it have to be a raw type and not a wildcard (`Bar>`)? Just because you don't always need to know the type argument(s) does not mean a type should not be parameterized. That's the whole point of wildcards. – Ben Schulz Sep 05 '12 at 14:11
  • @BenSchulz - Okay sure, "unless you revert to a raw type *or wildcard*, which defeats the purpose of expressing `T`". I think you may have missed my point. – Paul Bellora Sep 05 '12 at 14:27
  • @PaulBellora I'm not ruling out other subclasses (for which expressing `T` should have plenty purpose). I'm saying the class itself does not have to be abstract. I'm saying it's not like "it could never be used directly". – Ben Schulz Sep 05 '12 at 15:21
  • @BenSchulz - Okay, I see what you're saying. Yes, technically you're correct. If you want to pass around and interact with `Bar>`s, have fun. – Paul Bellora Sep 05 '12 at 16:02
4

This is very similar with the way java.lang.Enum class is defined:

public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
  private final String name;
  private final int ordinal;
  protected Enum(String name, int ordinal) {
    this.name = name; this.ordinal = ordinal;
  }
  public final String name() { return name; }
  public final int ordinal() { return ordinal; }
  public String toString() { return name; }
  public final int compareTo(E o) {
    return ordinal - o.ordinal;
  }
}

As the classes defined like this have to be abstract and cannot be instantiated directly, the pattern is useful in constructs similar with the way normal enums are expanded:

// corresponds to
// enum Season { WINTER, SPRING, SUMMER, FALL }
final class Season extends Enum<Season> {
  private Season(String name, int ordinal) { super(name,ordinal); }
  public static final Season WINTER = new Season("WINTER",0);
  public static final Season SPRING = new Season("SPRING",1);
  public static final Season SUMMER = new Season("SUMMER",2);
  public static final Season FALL   = new Season("FALL",3);
  private static final Season[] VALUES = { WINTER, SPRING, SUMMER, FALL };
  public static Season[] values() { return VALUES.clone(); }
  public static Season valueOf(String name) {
    for (Season e : VALUES) if (e.name().equals(name)) return e;
    throw new IllegalArgumentException();
  }

}

Example from book "Java Generics and Collection".

dcernahoschi
  • 14,968
  • 5
  • 37
  • 59
3

You are basically limiting the kinds of types that Bar will "deal with" to anything that extends Bar<T>. In this case, you want to make sure that Bar is only dealing with extensions of itself - maybe call a method that's private to Bar. One simple example is that you might use this class to implement a kind of linked list, and iterate over it while doing something that only Bar can/should do. Let's say you had the following code:

public class Bar<T extends Bar<T>> extends Foo<T> {
    private T next;

    //Initialize next in constructor or somewhere else

    private void doSomethingOnlyBarCanDo(){
        //Do it...
    }

    public void iterate(){
        T t = next;
        while(t != null){
            t.doSomethingOnlyBarCanDo();
            t = t.next;
        }
    }
}

With this kind of a construct, it'd be very easy to iterate over a "chain" of Bar instances, because each instance would have a reference to the next - recall that T extends Bar<T>, so you can refer to it as such.

CodeBlind
  • 4,519
  • 1
  • 24
  • 36
  • I can always call `doSomethingOnlyBarCanDo()` method because it is in the same class. So what so special about it? – Amit Deshpande Sep 04 '12 at 17:18
  • 1
    @AmitD You can only call `t.doSomethingOnlyBarCanDo();` if `t` is a `Bar`. – assylias Sep 04 '12 at 17:21
  • @student It's generally good practice to do something like this if it makes your code easier to maintain and understand, or if it hides something complex that shouldn't be exposed to outside classes. I personally like putting limitations on generics because it gives outside developers a better picture of what the class was intended to do. One thing that really muddies this up is academia's use of "Foo" and "Bar" as legitimate class names. They don't provide any sort of hint as to what those classes are supposed to do, they only tell you what the syntax is capable of. – CodeBlind Sep 04 '12 at 17:35
  • @assylias I was not satisfied with example that's it. So I had given mine.:) – Amit Deshpande Sep 04 '12 at 17:52
2

One typical use case is Wrapper/Decorator pattern. Bar probably wraps T that extends Bar itself. Foo is just a parametrized class that deals with T.

public abstract class Foo<T> {
    public abstract void foo(T t);
}

public class Bar<T extends Bar<T>> extends Foo<T> {
    private T wrapped;
    public Bar(T w) {
         this.wrapped = w;
    }

    public abstract void foo(T t) {
        // do something 
    }
}
AlexR
  • 114,158
  • 16
  • 130
  • 208
0

The only thing I could tell is <T extends Bar<T>> using this you tell that T is now of Type Bar<T> which means that T is Bar so you can access all the methods available to Bar, other wise if you only do Bar<T> you will not be able to access it as T would have been generic then.

What is the Use then ?

You can use this for composition. e.g.

public class CustomList<T extends List<T>> {
    T t;

    T get(int index) {
        //Some custom code here
        return t.get(index);
    }
}

Your example is bit wrong since there is no real advantage of Telling that T is of Type Bar since you will have always access to Bar class methods inside Bar class

Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72