编译错误与generics
test1和test2之间的区别在哪里? 为什么test1中的编译错误?
import java.util.ArrayList; import java.util.Collection; class MyType { } class MyClass { private Collection myTypes = new ArrayList(); private Collection myTs = new ArrayList(); public Collection getMyTypes() { return myTypes; } public Collection getMyTs() { return myTs; } } public class TestSimple { public void test1() { MyClass myClass = new MyClass(); for (MyType myType : myClass.getMyTypes()) { } } public void test2() { MyClass myClass = new MyClass(); Collection myTypes = myClass.getMyTypes(); for (MyType myType : myTypes) { } } public void test3() { MyClass myClass = new MyClass(); for (Long myType : myClass.getMyTs()) { } } }
如果你在一个类上定义一个generics约束,然后在没有提供任何generics约束的情况下实例化该类(也就是说,你完全不使用<>
),那么你刚刚进入了原始类型的领域,其中没有什么是再也一样了。
根据Java语言规范 :
原始类型的使用仅允许作为遗留代码兼容性的让步。 强烈建议不要在将通用性引入Java编程语言之后编写的代码中使用原始类型。 未来版本的Java编程语言可能会禁止使用原始类型。
根据Angelika Langer出色的Java Generics FAQ ,
原始类型的方法或构造函数具有在类型擦除之后将具有的签名。 如果擦除更改了参数类型,则对原始类型的方法或构造函数调用会生成未经检查的警告。
因此,通过将MyClass
构造为原始类型(即,作为MyClass
而不是MyClass>
), 您完全选择了generics ,并且getMyTypes()
的返回类型现在是原始类型Collection
,而不是Collection
。 因此,您不能使用类型为MyType
的增强型语法,而是必须使用Object
。
当然,更好的解决方案就是使用MyClass>
(而不仅仅是MyClass
),当您指的是未知参数化类型的MyClass
时。
我已将您的问题分离到一个较小的示例,我将在下面显示
import java.util.*; public class TestSimple { static class MyClass { private Collection myTypes = new ArrayList (); public Collection getMyTypes() { return myTypes; } } public void test1() { MyClass myClass = new MyClass(); for (String myType : myClass.getMyTypes()) { } } }
我怀疑所有类型的信息都被剥夺了,除非你特别说明。 所以我的建议是改变你的声明:
before: MyClass myClass = new MyClass(); after: MyClass> myClass = new MyClass();
Java对原始类型过于苛刻。 如果使用原始类型的generics类,则忽略类中的所有generics信息,即使是与类的类型参数无关的无效信息也是如此。
class A implements List Set var;
如果你使用原始A
,那么它被视为
class A implements List Set var;
这种严厉的处理是没有必要的; 他们可能不认为原始类型需要太多资源,因此他们采取了简单的方法,从原始类型中不加选择地删除每个通用信息。
在test2
由于您尚未参数化MyClass
,因此getMyTypes()
将有效地返回Collection
,而Collection
不能分配给Collection
。