为什么我不能在带有多个边界的类型参数中使用类型参数? [英] Why can't I use a type argument in a type parameter with multiple bounds?

查看:265
本文介绍了为什么我不能在带有多个边界的类型参数中使用类型参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 接口适配器< E> {} 

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

add / code>方法给我一个编译错误,当第一个绑定是类型参数(在Eclipse中)或类型参数不能后跟其他边界时不能指定任何附加绑定的适配器< E& ),请选择。



很明显,你只是不允许使用类型参数 I & ,就是这样。 (在你提出之前,如果你切换em,它不会工作,因为不能保证 I 不是一个具体的类。)但是为什么不呢?我已经查看了Angelika Langer的常见问题,但找不到答案。



一般来说,当一些泛型限制看起来是任意的,这是因为你创建了一种情况,系统实际上不能强制正确性。但我没有看到什么情况会打破我在这里想做的。我想说的可能是类型擦除后的方法分派,但只有一个 add()方法,因此它不像有任何歧义...



有人可以为我证明这个问题吗?

解决方案

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



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



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

  public static< T extends Comparable< ;?超级T>但是,这会删除:



  public static Comparable max(Collection coll)

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

  public static< T extends Object&可比较的超级T> T max(Collection< ;? extends T> coll)

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

  public static Object max(Collection coll)

这相当于泛型之前的 max 签名。



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



更多讨论交叉类型和限制的泛型在< a href =http://www.cs.rice.edu/~javaplt/papers/oopsla2008.pdf =nofollow noreferrer>即将推出的OOPSLA文件。


So, I understand that the following doesn't work, but why doesn't it work?

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));
    }
}

The add() method gives me a compile error, "Cannot specify any additional bound Adapter<E> when first bound is a type parameter" (in Eclipse), or "Type parameter cannot be followed by other bounds" (in IDEA), take your pick.

Clearly you're just Not Allowed to use the type parameter I there, before the &, and that's that. (And before you ask, it doesn't work if you switch 'em, because there's no guarantee that I isn't a concrete class.) But why not? I've looked through Angelika Langer's FAQ and can't find an answer.

Generally when some generics limitation seems arbitrary, it's because you've created a situation where the type system can't actually enforce correctness. But I don't see what case would break what I'm trying to do here. I'd say maybe it has something to do with method dispatch after type erasure, but there's only one add() method, so it's not like there's any ambiguity...

Can someone demonstrate the problem for me?

解决方案

I'm also not sure why the restriction is there. You could try sending a friendly e-mail to the designers of Java 5 Generics (chiefly Gilad Bracha and Neal Gafter).

My guess is that they wanted to support only an absolute minimum of intersection types (which is what multiple bounds essentially are), to make the language no more complex than needed. An intersection cannot be used as a type annotation; a programmer can only express an intersection when it appears as the upper bound of a type variable.

And why was this case even supported? The answer is that multiple bounds allow you to control the erasure, which allows to maintain binary compatibility when generifying existing classes. As explained in section 17.4 of the book by Naftalin and Wadler, a max method would logically have the following signature:

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

However, this erases to:

public static Comparable max(Collection coll)

Which does not match the historical signature of max, and causes old clients to break. With multiple bounds, only the left-most bound is considered for the erasure, so if max is given the following signature:

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

Then the erasure of its signature becomes:

public static Object max(Collection coll)

Which is equal to the signature of max before Generics.

It seems plausible that the Java designers only cared about this simple case and restricted other (more advanced) uses of intersection types because they were just unsure of the complexity that it might bring. So the reason for this design decision does not need to be a possible safety problem (as the question suggests).

More discussion on intersection types and restrictions of generics in an upcoming OOPSLA paper.

这篇关于为什么我不能在带有多个边界的类型参数中使用类型参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆