java – 为什么我不能在带有多个边界的类型参数中使用类型参数?

所以,我明白以下不工作,但为什么不工作?

interface Adapter<E> {}

class Adaptulator<I> {
    <E, A extends I & Adapter<E>> void add(Class<E> extl, Class<A> intl) {
        addAdapterFactory(new AdapterFactory<E, A>(extl, intl));
    }
}

add()方法给我一个编译错误,“当第一个绑定是类型参数”(在Eclipse中)或“类型参数不能后跟其他边界”(在IDEA中)时,不能指定任何附加绑定的适配器< E&拿你的选择。 显然,你只是不允许使用类型参数我在那里,在&之前,这就是。 (在你问之前,如果你切换,不会工作,因为不能保证我不是一个具体的类。)但为什么不呢?我看过Angelika Langer的常见问题,找不到答案。 一般来说,当一些泛型限制看起来是任意的,这是因为你创建了一种情况,类型系统不能实际强制正确性。但我不明白什么情况会打破我在这里想做的。我想说,它可能与方法调度类型擦除后有关,但只有一个add()方法,所以它不像有任何歧义… 有人可以为我演示这个问题吗?

最佳答案
我也不知道为什么限制是有。你可以尝试发送一封友好的电子邮件给Java 5 Generics的设计师(主要是Gilad Bracha和Neal Gafter)。

我的猜测是,他们只想支持绝对最小值为intersection types(这是多重边界本质上是),使语言不再复杂的需要。交集不能用作类型注释;一个程序员只能在出现一个类型变量的上界时表达一个交集。

为什么这种情况甚至支持?答案是多个边界允许您控制擦除,这允许在生成现有类时保持二进制兼容性。如Naftalin和Wadler在book的17.4节中所解释的,最大方法在逻辑上具有以下签名:

public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll)

但是,这会删除:

public static Comparable max(Collection coll)

这与max的历史签名不匹配,并导致旧客户端中断。
对于多个边界,只有最左边界被考虑用于擦除,因此如果max被给予以下签名:

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

然后,其签名的擦除变为:

public static Object max(Collection coll)

这等于在通用之前的最大签名。

看起来似乎是合理的,Java设计者只关心这个简单的情况并限制交叉类型的其他(更高级)使用,因为他们只是不确定它可能带来的复杂性。因此,这个设计决策的原因不需要是一个可能的安全问题(如问题所暗示的)。

更多讨论在交叉路口类型和限制的泛型在upcoming OOPSLA paper

转载注明原文:java – 为什么我不能在带有多个边界的类型参数中使用类型参数? - 代码日志