当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《为什么我不能在具有多个边界的类型参数中使用类型参数?》经验,为你挑选了3个好方法。

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

interface Adapter {}

class Adaptulator {
    > void add(Class extl, Class intl) {
        addAdapterFactory(new AdapterFactory(extl, intl));
    }
}

add()方法给出了一个编译错误,"当第一个绑定是一个类型参数时,无法指定任何其他绑定的适配器"(在Eclipse中),或者"类型参数不能跟随其他边界"(在IDEA中),请选择.

很明显,你只是不允许在I那之前使用type参数&,那就是那个.(而且在你问之前,如果你改变它们就行不通,因为不能保证它I不是一个具体的类.)但为什么不呢?我查看了Angelika Langer的常见问题解答并找不到答案.

通常,当某些泛型限制看似随意时,这是因为您创建了一种类型系统无法实际执行正确性的情况.但我不知道哪种情况会破坏我在这里要做的事情.我可能会说它可能与类型擦除后的方法调度有关,但是只有一种add()方法,所以它不像是有任何歧义......

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



1> Bruno De Fra..:

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

我的猜测是,他们只想支持绝对最小的交集类型(这实际上是多个边界),使语言不再需要复杂.交集不能用作类型注释; 程序员只能在表示为类型变量的上限时表达交集.

为什么这个案子甚至得到支持?答案是多边界允许您控制擦除,这允许在生成现有类时保持二进制兼容性.正如Naftalin和Wadler 所着的第17.4节所解释的那样,一种max方法在逻辑上具有以下特征:

public static > T max(Collection coll)

然而,这抹去了:

public static Comparable max(Collection coll)

哪个与历史签名不符max,并导致旧客户中断.对于多个边界,只考虑最左边的边界进行擦除,因此如果max给出以下签名:

public static > T max(Collection coll)

然后删除其签名变为:

public static Object max(Collection coll)

这等于maxGenerics之前的签名.

似乎有理由认为Java设计者只关心这个简单的情况并限制了交集类型的其他(更高级)用途,因为他们只是不确定它可能带来的复杂性.因此,这个设计决策的原因不一定是一个可能的安全问题(如问题所示).

关于即将发布的OOPSLA论文中关于交叉类型和泛型限制的更多讨论.



2> Chris Povirk..:

禁止这种情况的两个可能原因:

    复杂. Sun bug 4899305建议包含类型参数和其他参数化类型的绑定将允许比已经存在的更复杂的相互递归类型.简而言之,布鲁诺的回答.

    指定非法类型的可能性.具体来说,使用不同的参数扩展通用接口两次.我无法想出一个非人为的例子,但是:

    /** Contains a Comparator that also implements the given type T. */
    class StringComparatorHolder> {
      private final C comparator;
      // ...
    }
     
    void foo(StringComparatorHolder, ?> holder) { ... }

现在holder.comparator是一个Comparator和一个Comparator.我不清楚这会给编译器造成多大的麻烦,但显然不是很好.假设特别是Comparator有这样的方法:

void sort(List list);

我们的Comparator/ Comparatorhybrid现在有两种方法具有相同的擦除:

void sort(List list);
void sort(List list);

出于这些原因,您无法直接指定此类型:

 & Comparator> void bar() { ... }
java.util.Comparator cannot be inherited with different arguments:
     and 

既然>允许你间接地做同样的事情,那也是.


有趣.不得不考虑一下这一点.无论如何,仍然似乎编译器会抓住它 - 在foo()的声明中.但也许有一个更加人为的例子可以让它更清晰.:) James Iry说它适用于Scala:http://www.chrononaut.org/showyourwork/?p = 52 #comment-46

3> Jan Soltis..:

这是JLS的另一个引用:

限制的形式是受限制的(只有第一个元素可以是类或类型变量,并且只有一个类型变量可以出现在边界中)以排除某些尴尬的情况出现.

那些尴尬的情况究竟是什么,我不知道.

推荐阅读
jerry613
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有