gpt4 book ai didi

java - 泛型:T extends MyClass 与 T extends MyClass

转载 作者:太空狗 更新时间:2023-10-29 22:56:26 25 4
gpt4 key购买 nike

这两个声明之间是否存在语义差异,还是只是语法糖?

class C<T extends C>对比class C<T extends C<T>>

背景:我最近回答了一个 question关于使用 C<T extends C> 的泛型方法和同行基于 C<T extends C<T>> 提供了类似的答案.最后,两种选择都提供了相同的结果(在所问问题的上下文中)。我仍然对这两种构造之间的区别感到好奇。

是否存在语义差异?如果是这样,每种方法的含义和后果是什么?

最佳答案

当然 - 通常这些“ self 类型”用于约束子类型以完全返回它们自己的类型。考虑以下内容:

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
}

这将被编译器拒绝,因为泛型类型不在其范围内。这非常重要——这意味着在父类中,即使我们不知 Prop 体类型是什么(甚至可能是编译时不存在的类),copy()方法将返回同一子类的实例。

如果您只是选择 C<T extends C> ,然后这个奇怪的定义 SubtractOperation 是合法的,你失去了关于什么的保证 T在这种情况下 - 因此减法运算可以将自身复制到加法运算中。

这与其说是为了保护您的类层次结构免受恶意子类的侵害,不如说是它为编译器提供了有关所涉及类型的更强有力的保证。如果你调用 copy来自另一个类(class)的任意 Operation ,您的一个构造保证结果将属于同一类,而另一个将需要转换(并且可能不是正确的转换,如上面的 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对于您提出的两个界限中较弱的一个,不会是类型安全的,因此代码无法编译。 即使您明智地定义了所有子类。

关于java - 泛型:T extends MyClass 与 T extends MyClass<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6523108/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com