所以,我的理解是以下不工作,但为什么不工作?
interface Adapter{} class Adaptulator { > void add(Class extl, Class intl) { addAdapterFactory(new AdapterFactory (extl, intl)); } }
该add()
方法给出了一个编译错误,"当第一个绑定是一个类型参数时,无法指定任何其他绑定的适配器
很明显,你只是不允许在I
那之前使用type参数&
,那就是那个.(而且在你问之前,如果你改变它们就行不通,因为不能保证它I
不是一个具体的类.)但为什么不呢?我查看了Angelika Langer的常见问题解答并找不到答案.
通常,当某些泛型限制看似随意时,这是因为您创建了一种类型系统无法实际执行正确性的情况.但我不知道哪种情况会破坏我在这里要做的事情.我可能会说它可能与类型擦除后的方法调度有关,但是只有一种add()
方法,所以它不像是有任何歧义......
有人能为我证明这个问题吗?
我也不确定为什么会有限制.您可以尝试向Java 5 Generics(主要是Gilad Bracha和Neal Gafter)的设计师发送友好的电子邮件.
我的猜测是,他们只想支持绝对最小的交集类型(这实际上是多个边界),使语言不再需要复杂.交集不能用作类型注释; 程序员只能在表示为类型变量的上限时表达交集.
为什么这个案子甚至得到支持?答案是多边界允许您控制擦除,这允许在生成现有类时保持二进制兼容性.正如Naftalin和Wadler 所着的第17.4节所解释的那样,一种max
方法在逻辑上具有以下特征:
public static> T max(Collection extends T> coll)
然而,这抹去了:
public static Comparable max(Collection coll)
哪个与历史签名不符max
,并导致旧客户中断.对于多个边界,只考虑最左边的边界进行擦除,因此如果max
给出以下签名:
public static> T max(Collection extends T> coll)
然后删除其签名变为:
public static Object max(Collection coll)
这等于max
Generics之前的签名.
似乎有理由认为Java设计者只关心这个简单的情况并限制了交集类型的其他(更高级)用途,因为他们只是不确定它可能带来的复杂性.因此,这个设计决策的原因不一定是一个可能的安全问题(如问题所示).
关于即将发布的OOPSLA论文中关于交叉类型和泛型限制的更多讨论.
禁止这种情况的两个可能原因:
复杂. Sun bug 4899305建议包含类型参数和其他参数化类型的绑定将允许比已经存在的更复杂的相互递归类型.简而言之,布鲁诺的回答.
指定非法类型的可能性.具体来说,使用不同的参数扩展通用接口两次.我无法想出一个非人为的例子,但是:
/** Contains a Comparatorthat also implements the given type T. */ class StringComparatorHolder > { private final C comparator; // ... } void foo(StringComparatorHolder , ?> holder) { ... }
现在holder.comparator
是一个Comparator
和一个Comparator
.我不清楚这会给编译器造成多大的麻烦,但显然不是很好.假设特别是Comparator
有这样的方法:
void sort(List extends T> list);
我们的Comparator
/ Comparator
hybrid现在有两种方法具有相同的擦除:
void sort(List extends Integer> list); void sort(List extends String> list);
出于这些原因,您无法直接指定此类型:
& Comparator > void bar() { ... }
java.util.Comparator cannot be inherited with different arguments:and
既然>
允许你间接地做同样的事情,那也是.
这是JLS的另一个引用:
限制的形式是受限制的(只有第一个元素可以是类或类型变量,并且只有一个类型变量可以出现在边界中)以排除某些尴尬的情况出现.
那些尴尬的情况究竟是什么,我不知道.