【发布时间】:2012-08-29 09:11:44
【问题描述】:
我正在尝试理解以下内容的含义?
public class Bar<T extends Bar<T>> extends Foo<T> {
//Some code
}
做这样的事情有什么好处(例如用例?)。
【问题讨论】:
我正在尝试理解以下内容的含义?
public class Bar<T extends Bar<T>> extends Foo<T> {
//Some code
}
做这样的事情有什么好处(例如用例?)。
【问题讨论】:
这与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 泛型与集合”一书中的示例。
【讨论】:
这是一个相当理论的例子,但在这种情况下你可能需要它:
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();
}
}
}
如果 T 不是 Bar,您将无法调用 param.getValue(),这是因为 T extends Bar<T>。
【讨论】:
Bar 应该是抽象的,因为它永远不能直接使用。在这里查看我的答案:stackoverflow.com/questions/7354740/…
java.lang.Enum 的定义非常相似:public abstract class Enum<E extends Enum<E>> implements Comparable<E>
static <T extends Bar<T>> Bar<T> createBar() { return new Bar<T>(); } 怎么样?
我唯一能说的是<T extends Bar<T>> 使用这个你告诉T 现在是Bar<T> 类型,这意味着T 是Bar 所以你可以访问Bar 可用的所有方法,否则如果你只做Bar<T>,你将无法访问它,因为T那时是通用的。
那有什么用呢?
你可以用它来作曲。例如
public class CustomList<T extends List<T>> {
T t;
T get(int index) {
//Some custom code here
return t.get(index);
}
}
您的示例有点错误,因为告诉 T 属于 Bar 类型并没有真正的优势,因为您将始终可以访问 Bar 类中的 Bar 类方法
【讨论】:
您基本上将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 实例的“链”,因为每个实例都会引用下一个实例 - 回想一下 T 扩展 Bar<T>,所以你可以这样引用它。
【讨论】:
doSomethingOnlyBarCanDo() 方法,因为它在同一个类中。那么它有什么特别之处呢?
t 是Bar,您只能调用t.doSomethingOnlyBarCanDo();。
一个典型的用例是包装器/装饰器模式。 Bar 可能包装了 T 扩展 Bar 本身。 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
}
}
【讨论】:
public class Bar<T> extends Foo<T>