当我尝试调试你的代码时,我发现了一些非常有趣的事情。为了解决编译器错误:
错误:类型不匹配:无法从元素类型Object转换为HelloWorld.Type
由于它声明返回的元素是Object
类型,因此我决定将其强制转换为List<Type>
,如下所示:
public static void main( String[] args ) {
for ( Type type : (List<Type>)new HelloWorld().getTypes() ) {
}
}
这段代码编译成功了,但有警告。为了查看警告信息,我使用了-Xlint
和javac
命令,并发现以下内容:
HelloWorld.java:15: warning: [rawtypes] found raw type: HelloWorld
for ( Type type : (List<Type>)new HelloWorld().getTypes() ) {
^
missing type arguments for generic class HelloWorld<T>
where T is a type-variable:
T extends Object declared in class HelloWorld
HelloWorld.java:15: warning: [unchecked] unchecked cast
for ( Type type : (List<Type>)new HelloWorld().getTypes() ) {
^
required: List<Type>
found: List
2 warnings
在这里,我惊讶地看到了第二个警告。它指出所需的是 List<Type>
,但发现是一个 List
的原始类型。因此,这意味着如果您初始化一个原始类型对象并调用返回具有泛型的变量的方法,则该变量也将转换为原始类型。为了测试这个,我实现了一个名为 HelloWorldTest
的类:
public class HelloWorldTest<T>{
private T t;
public HelloWorldTest(T t){
this.t = t;
}
public T getT(){
return t;
}
}
然后我更改了你的代码,将条件测试改为:
public class HelloWorld<T> {
private HelloWorldTest<Integer> test = new HelloWorldTest<>(1);
public HelloWorldTest<Integer> getTest(){
return test;
}
public static void main( String[] args ) {
HelloWorldTest<Integer> hello = new HelloWorld().getTest();
}
}
这个代码可以成功编译,但是会有警告信息,所以使用-Xlint
开关进行编译时会得到以下警告:
HelloWorld.java:10: warning: [rawtypes] found raw type: HelloWorld
HelloWorldTest<Integer> hello = new HelloWorld().getTest();
^
missing type arguments for generic class HelloWorld<T>
where T is a type-variable:
T extends Object declared in class HelloWorld
HelloWorld.java:10: warning: [unchecked] unchecked conversion
HelloWorldTest<Integer> hello = new HelloWorld().getTest();
^
required: HelloWorldTest<Integer>
found: HelloWorldTest
2 warnings
因此,我们发现HelloWorldTest
也被转换为原始类型。
最后我们可以得出结论:如果你初始化一个原始类型对象并调用返回泛型变量的方法,则该变量也将被转换为原始类型。
现在当我替换时
HelloWorldTest<Integer> hello = new HelloWorld().getTest();
带有。
Integer hello = new HelloWorld().getTest().getT();
正如预期的那样,我收到了错误消息:
HelloWorld.java:10: error: incompatible types: Object cannot be converted to Integer
Integer hello = new HelloWorld().getTest().getT();
^
1 error
最后,如果你用我的HelloWorld
类实现中替换主方法为:
public static void main( String[] args ) {
String hello = (String) new HelloWorld().getTest().getT();
}
它成功编译,唯一的警告是:
。
(保留HTML标签)
HelloWorld.java:10: warning: [rawtypes] found raw type: HelloWorld
String hello = (String) new HelloWorld().getTest().getT();
^
missing type arguments for generic class HelloWorld<T>
where T is a type-variable:
T extends Object declared in class HelloWorld
1 warning
这种说法非常误导人,因为它肯定会遇到运行时错误,并再次说明了在泛型中使用
原始类型的危险。
HelloWorld.java:17: error: incompatible types: Object cannot be converted to Type
。 - DragondraikkHelloWorld
,并且在没有参数的情况下进行了初始化:new HelloWorld<TYPE_NEEDED>()
。 - MaxZoom