12

我想了解以下内容是什么意思?

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

做这样的事情有什么好处(例如用例?)。

4

5 回答 5

7

这是一个相当理论的例子,但在这种情况下你可能需要它:

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();
        }
    }
}

param.getValue()如果 T 不是 a ,您将无法调用Bar,这是因为T extends Bar<T>

于 2012-09-04T17:00:38.560 回答
4

这与定义类的方式非常相似java.lang.Enum

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

由于像这样定义的类必须是抽象的并且不能直接实例化,因此该模式在类似于普通枚举扩展方式的构造中很有用:

// 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();
  }

}

来自“Java 泛型和集合”一书中的示例。

于 2012-09-04T20:30:02.903 回答
3

Bar您基本上将“处理”的类型限制为扩展的任何类型Bar<T>。在这种情况下,你要确保Bar它只处理自身的扩展——也许调用一个私有的方法Bar。一个简单的例子是,你可以使用这个类来实现一种链表,并在做一些只能Bar/应该做的事情时对其进行迭代。假设您有以下代码:

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

使用这种构造,迭代“链”Bar实例非常容易,因为每个实例都会引用下一个实例 - 回忆一下Textends Bar<T>,所以你可以这样引用它。

于 2012-09-04T17:06:41.393 回答
2

一个典型的用例是 Wrapper/Decorator 模式。Bar可能会包裹TBar本身。Foo只是一个处理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 
    }
}
于 2012-09-04T17:03:18.567 回答
0

我唯一能说的是<T extends Bar<T>>使用这个你告诉T现在的类型Bar<T>,这意味着你可以访问所有可用的方法,否则如果你只这样做,T你将无法访问它,因为那将是通用的.BarBarBar<T>T

那有什么用呢?

您可以将其用于合成。例如

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

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

您的示例有点错误,因为 Telling that T is of Type Bar 没有真正的优势,因为您始终可以访问 Bar 类中的 Bar 类方法

于 2012-09-04T17:22:34.963 回答