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

大卫·摩尔:

所以,我的理解下列哪项不工作,但为什么不工作?

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()方法给我一个编译错误,“当第一个绑定是类型参数时,不能指定任何其他绑定Adapter <E>”(在Eclipse中),或“在类型参数后不能跟其他边界”(在IDEA中),请选择。

显然,你只是不允许使用类型参数I出现,之前的&,就是这样。(在您问之前,如果您切换它们,那I是行不通的,因为不能保证这不是具体的课程。)但是为什么不呢?我已经查看了Angelika Langer的常见问题解答,但找不到答案。

通常,当某些泛型限制似乎是任意的时,这是因为您造成了类型系统实际上无法强制正确性的情况。但是我看不出什么情况会破坏我在这里试图做的事情。我想说这可能与类型擦除后的方法分派有关,但是只有一种add()方法,所以这并不意味着有任何歧义。

有人可以为我演示问题吗?

布鲁诺·德·弗赖恩(Bruno De Fraine):

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

我的猜测是,他们只想支持绝对最小的交集类型(本质上就是多个边界),以使语言不会比需要的复杂。相交不能用作类型注释;程序员仅在交集出现为类型变量的上限时才可以表达交集。

为何甚至支持这种情况?答案是,多个范围允许您控制擦除,这可以在生成现有类时保持二进制兼容性。正如Naftalin和Wadler 该书第17.4节中所解释的那样,一种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前泛型的签名

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

即将发布的OOPSLA论文中,将更多地讨论交集类型和泛型的限制

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么我不能在Java中创建类型参数数组?

为什么Java枚举文字不能具有通用类型参数?

不能在返回参数中使用msgs(类型<-chan _)作为类型chan _

不能在func的参数中使用子项(类型[] Child)作为类型[] Node

为什么不能在函数参数类型中使用模板参数包作为其模板参数列表,所以不能明确指定

Scala:使用类型参数或抽象类型作为类型界限

为什么ParsecT类型具有'u'参数?

为什么不能在C#中将null转换为类型T的参数?

为什么我不能在带有类型参数的特征上添加一揽子暗示?

为什么在此示例中参数b具有类型a?

为什么不能在带丢弃参数的lambda中使用丢弃参数?

FunctionK的类型参数的界限

为什么参数“ props”隐式具有“ any”类型?

c ++不能在构造函数中使用父类型作为参数

为什么带有约束的通用参数类型不能匹配模式,而直接使用约束类型呢?

为什么我不能在Kotlin中将Class类型用作通用参数?

为什么我不能在Dart 2中使用通用类型作为参数?

非类型模板参数不能具有类型

为什么我不能在MMT中使用类型参数定义(使用PLF)?

为什么在C ++中使用非类型参数?

为什么我不能在参数中使用通配符类型进行计算

为什么不能在类型扩展的约束中使用通用类型参数?

为什么不能推断委托参数的类型?

为什么不能从具有通用参数的类型转换为通用接口,该类型是接口中通用参数的子类型?

当最新的过程是“通知发送”时,为什么不能在Bash中使用带有参数扩展功能的`kill $!`?

为什么不能在函数参数列表中使用匿名对象作为参数?C ++

具有多个参数的类型的GenericTypeDefinition

Golang 错误:不能在中位数的参数中使用 (type [5]int) 作为 int 类型

为什么不能在 for 循环中使用类型提示?