我正在尝试理解以下内容的含义:
public class Bar<T extends Bar<T>> extends Foo<T> {
//Some code
}
做这样的事情有什么好处(例如使用案例)?
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();
}
}
}
这与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 Generics and Collection》的示例。
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()
方法,因为它和当前类在同一个类中。那这个方法有什么特别之处呢? - Amit Deshpandet
是一个Bar
对象时,你才能调用t.doSomethingOnlyBarCanDo();
。 - assylias一个典型的用例是包装器/修饰器模式。 Bar
可能会包装扩展了 Bar
本身的 T
。 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
}
}
<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);
}
}
你的例子有点不对,因为在 Bar 类中,你总是可以访问到 Bar 类的方法,所以告诉 T 是 Bar 类型并没有真正的优势。
Bar
应该是抽象的,因为它永远不能直接使用。请参见我的答案:https://dev59.com/vGs05IYBdhLWcg3wQvke#7355094 - Paul Bellorajava.lang.Enum
的定义非常相似:public abstract class Enum<E extends Enum<E>> implements Comparable<E>
。 - dcernahoschiT
应该有很多目的)。我是说这个类本身不一定要是抽象的。我的意思是它不像“永远不能直接使用”。 - Ben Schulz