Java 8类型推断导致在调用时省略泛型类型
升级到
Java 1.8后,我遇到了一个泛型方法的问题,这对于Java 1.6和1.7来说很好
请考虑以下代码: public class ExtraSortList<E> extends ArrayList<E> { ExtraSortList(E... elements) { super(Arrays.asList(elements)); } public List<E> sortedCopy(Comparator<? super E> c) { List<E> sorted = new ArrayList<E>(this); Collections.sort(sorted,c); return sorted; } public static void main(String[] args) { ExtraSortList<String> stringList = new ExtraSortList<>("foo","bar"); Comparator<? super String> compGen = null; String firstGen = stringList.sortedCopy(compGen).get(0); // works fine Comparator compRaw = null; String firstRaw = stringList.sortedCopy(compRaw).get(0); // compiler ERROR: Type mismatch: cannot convert from Object to String } } 我尝试使用Oracle javac(1.8.0_92)和Eclipse JDT(4.6.1)编译器.两者都是一样的结果. (错误消息有点不同,但基本相同) 除了事实,可以通过避免原始类型来防止错误,它让我困惑,因为我不明白原因. 为什么sortedCopy-Method的raw方法参数对返回值的泛型类型有任何影响?泛型类型已在类级别定义.该方法未定义单独的泛型类型.引用列表的类型为< String>,返回的List也应如此. 为什么Java 8会在返回值上丢弃类中的泛型类型? 编辑:如果sortedCopy的方法签名被更改(由biziclop指出) public List<E> sortedCopy(Comparator c) { 那么编译器确实从类型ExtraSortList< E>中考虑通用类型E.并且不会出现错误.但是现在参数c是原始类型,因此编译器无法验证提供的Comparator的泛型类型. 编辑:我做了一些Java语言规范的评论,现在我想一想,我是否缺乏理解,或者这是编译器的一个缺陷.因为: > Scope of a Declaration的泛型类型E是ExtraSortList类,它包括方法sortedCopy.
>引用stringList是使用String定义的,因此编译器不需要在sortedCopy的调用中推断类型forE,因为它已经定义. 这是我目前对我认为Java编译器应如何评估调用的理解.如果我错了,解释为什么我的假设是错误的将是很好的. 解决方法
为了解决这个问题的最终答案:
就像@Jesper已经提到的那样,你不应该使用原始类型(特别是在多种情况下使用Generic作为类型). public List sortedCopy(Comparator c) { List sorted = new ArrayList(this); Collections.sort(sorted,c); return sorted; } 现在你正在尝试/假设你从没有泛型的List中得到一个String,因此得到一个Object(因此它是所有东西的超类). 关于为什么raw-type参数对返回类型没有影响的问题,因为你没有指定某个抽象级别.例如,您必须定义Generic必须扩展/实现的类型,以至少实现这一点(编译错误). public class ExtraSortList<E extends String> extends ArrayList<E> { 现在只允许扩展它的字符串或类(这里不可能,因为字符串是最终的).有了它,你的后备类型将是String. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |