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

标签 java generics constraints

所以,我了解以下行不通,但为什么行不通?

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() 方法给我一个编译错误,“当第一次绑定(bind)是类型参数时,不能指定任何额外的绑定(bind)适配器”(在 Eclipse 中),或者“类型参数不能其次是其他界限”(在 IDEA 中),任君选择。

显然,您只是不允许在 & 之前使用类型参数 I,仅此而已。 (在你问之前,如果你切换它们是行不通的,因为不能保证 I 不是一个具体的类。)但为什么不呢?我浏览了 Angelika Langer 的常见问题解答,但找不到答案。

通常,当某些泛型限制看起来很随意时,这是因为您创建了类型系统实际上无法强制正确性的情况。但我不知道什么情况会破坏我在这里尝试做的事情。我会说也许它与类型删除后的方法调度有关,但是只有一个 add() 方法,所以它不像有任何歧义......

有人可以为我演示一下这个问题吗?

最佳答案

我也不确定为什么会有限制。您可以尝试向 Java 5 泛型的设计者(主要是 Gilad Bracha 和 Neal Gafter)发送一封友好的电子邮件。

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

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

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)

等于max在Generics之前的签名。

Java 设计人员只关心这种简单的情况并限制交集类型的其他(更高级)使用似乎是合理的,因为他们只是不确定它可能带来的复杂性。所以这个设计决定的原因不一定是一个可能的安全问题(正如问题所暗示的那样)。

upcoming OOPSLA paper 中更多关于泛型的交集类型和限制的讨论.

关于java - 为什么我不能在具有多个边界的类型参数中使用类型参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/197190/

相关文章:

sql - MS SQL "ON DELETE CASCADE"多个外键指向同一个表?

双时态数据库的约束

java - GWT 验证输入到文本框中的时间 - 将长类型结果转换为 24 小时格式时出错

java - 无法在溢出的构造函数中默认参数

java - 如果我在 JSP 中有 html 元素,那么执行顺序是什么?

java - Gson,带有泛型的 ClassCastException

java - 如何使用 Mersenne Twister RNG 随机数生成器

ios - 在 Swift 中使用泛型数组作为参数的函数

ios - 从通用返回类型获取实际类型