当然 - 通常这些“自我类型”用于约束子类型以完全返回它们自己的类型。考虑以下内容:
public interface Operation {
// This bit isn't very relevant
int operate(int a, int b);
}
public abstract class AbstractOperation<T extends AbstractOperation<T>> {
// Lets assume we might need to copy operations for some reason
public T copy() {
// Some clever logic that you don't want to copy and paste everywhere
}
}
很酷 - 我们有一个父类,它带有一个有用的运算符,可以特定于子类。例如,如果我们创建一个AddOperation,它的泛型参数可以是什么?由于“递归”的泛型定义,这只能是 AddOperation 给我们的:
public class AddOperation extends AbstractOperation<AddOperation> {
// Methods etc.
}
因此copy() 方法保证返回AddOperation。现在让我们假设我们很傻、或恶意、或有创意或其他什么,并尝试定义这个类:
public class SubtractOperation extends AbstractOperation<AddOperation> {
// Methods etc.
// Because of the generic parameters, copy() will return an AddOperation
}
这将被编译器拒绝,因为泛型类型不在其范围内。这很重要——这意味着在父类中,即使我们不知道具体类型是什么(甚至可能是编译时不存在的类),copy() 方法也会返回同一个子类的一个实例。
如果你只是简单地使用C<T extends C>,那么SubtractOperation 的这个奇怪定义将是合法的,并且你失去了T 在这种情况下是什么的保证 - 因此减法运算可以将自身复制到添加操作中。
这并不是为了保护您的类层次结构免受恶意子类的侵害,更多的是它为编译器提供了对所涉及类型的更强有力的保证。如果您在任意Operation 上从另一个类调用copy,则您的一种形式保证结果将属于同一类,而另一种则需要强制转换(并且可能不是正确的演员表,就像上面的 SubtractOperation 一样)。
例如这样的:
// This prelude is just to show that you don't even need to know the specific
// subclass for the type-safety argument to be relevant
Set<? extends AbstractOperation> operations = ...;
for (AbstractOperation<?> op : operations) {
duplicate(op);
}
private <T extends AbstractOperation<T>> Collection<T> duplicate(T operation) {
T opCopy = operation.copy();
Collection<T> coll = new HashSet<T>();
coll.add(operation);
coll.add(opCopy);
// Yeah OK, it's ignored after this, but the point was about type-safety! :)
return coll;
}
duplicate 到 T 的第一行的赋值不会是类型安全的,因为您建议的两个边界较弱,因此代码无法编译。 即使你合理地定义了所有的子类。