Java泛型与通配符在Eclipse中编译,但不在javac中
作为后续的
Java generics compile in Eclipse,but not in javac,我发布另一个在Eclipse中编译和运行良好的代码段,但在javac中引发了一个编译错误. (这样可以防止该项目从Maven构建中提取该代码段.)
自包含的片段: import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; public class Main { public static void main(String[] args) { Set<Foo<?>> setOfFoos = new HashSet<Foo<?>>(); List<Foo<?>> sortedListOfFoos = asSortedList(setOfFoos); } public static <T extends Comparable<T>> List<T> asSortedList(Collection<T> c) { List<T> list = new ArrayList<T>(c); java.util.Collections.sort(list); return list; } public static class Foo<T> implements Comparable<Foo<T>> { @Override public int compareTo(Foo<T> o) { return 0; } } } javac中的编译返回: Main.java:11: <T>asSortedList(java.util.Collection<T>) in Main cannot be applied to (java.util.Set<Main.Foo<?>>) List<Foo<?>> sortedListOfFoos = asSortedList(setOfFoos); ^ 取代Foo?与Foo< String>上面的代码段将在javac中编译,这意味着问题与使用的通配符相关.由于Eclipse编译器应该更宽容,所以代码片段可能不是有效的Java? (我使用javac 1.6.0_37和Eclipse Indigo,编译器符合级别1.6) (EDIT1:包括在EDIT2中被删除的另一个例子) EDIT2:irreputable提示,比较Foo A和Foo B可能在概念上是错误的,灵感来自seh的答案,一个工作的asSortedFooList可以写成如下: public static <T extends Foo<?>> List<T> asSortedFooList(Collection<T> c) { List<T> list = new ArrayList<T>(c); java.util.Collections.sort(list); return list; } (在上述方法定义中用Foo< T>简单替换可比较的< T>) EDIT3:Rafaelle后来指出,设计中存在缺陷,因为实现了可比较的< Foo>>不是必需的,并且实现可比较的< Foo>>提供相同的功能,通过精心设计解决初始问题. (最初的原因和好处是,Foo&T可能在某些目的上不关心其具体类型,但仍然使用具体类型T的实例,为了其他目的,它被实例化,这种情况不必用于确定其他Foos之间的顺序,因为它可能用于API的其他部分. 具体示例:假设每个Foo用T的不同类型参数实例化.Foo的每个实例具有类型int的递增id,用于实现compareTo方法.我们现在可以对这些不同类型的Foo进行排序,并且不关心具体的类型T(用Foo表示),并且还有一个具体类型T的实例可以进行后续处理.) 解决方法
对我来说这是另一个javac bug.当您尝试发送Collection< Foo<?>>具有签名的方法:
public static <T extends Comparable<T>> List<T> asSortedList(Collection<T> c) 编译器注意到形式参数T有一个上限,所以检查被约束是否受到调用者的尊重. type参数是参数化类型Foo< T>的(通配符)实例化,因此如果Foo<> is-a Comparable< Foo<>>.基于通用定义: class Foo<T> implements Comparable<Foo<T>> 我会说这是真的,所以Eclipse是正确的,javac有一个错误.这个Angelika Langer’s entry从来没有足够的联系.另见the relevant JLS. 你问是否类型安全?我的答案是它是类型安全的,它表明你的设计有缺陷.考虑您的虚拟实施可比较的< T>界面,我添加了两个字段: public static class Foo<T> implements Comparable<Foo<T>> { private T pState; private String state; @Override public int compareTo(Foo<T> other) { return 0; } } 你总是返回0,所以没有发现问题.但是当您尝试使其有用时,您有两个选择: >比较字符串字段 String字段始终是一个String,所以你不会从类型变量T中受益.另一方面,T没有其他类型的信息可用,所以在compareTo()中,你只能处理一个普通的对象,并且再次该类型参数是无用的.您可以通过实现Comparable< Foo<?>>>实现相同的精确功能. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- java – 如何以正确的方式创建Scala项目?
- java实现遍历Map的方法
- eclipse中导入项目外部的jar包时出现.classpath can`t be w
- JSP application.getMinorVersion()方法:返回服务器支持的
- 一个小巧的HTML编辑器_CLEditor_源码下载
- iOS实现远程推送原理及过程
- 如何在Java SWING中设置自定义字体的大小和其他属性(粗体,斜
- 基于java使用JavaMail发送邮件
- 使用robot.moveMouse()时,JavaFX KeyEvents被延迟
- java – com.fasterxml.jackson.databind.JsonMappingExcep