student
student

Reputation: 167

Java generics syntax

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?).

Upvotes: 12

Views: 296

Answers (5)

dcernahoschi
dcernahoschi

Reputation: 15230

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".

Upvotes: 4

assylias
assylias

Reputation: 328598

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>.

Upvotes: 7

Amit Deshpande
Amit Deshpande

Reputation: 19185

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

Upvotes: 0

CodeBlind
CodeBlind

Reputation: 4569

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.

Upvotes: 3

AlexR
AlexR

Reputation: 115328

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 
    }
}

Upvotes: 2

Related Questions