Java 为什么这段代码不是';不可编译
这里是一小段代码,我不明白为什么javac不能编译它。我想念什么?有什么错误吗Java 为什么这段代码不是';不可编译,java,generics,Java,Generics,这里是一小段代码,我不明白为什么javac不能编译它。我想念什么?有什么错误吗 public class HelloWorld<T> { private static enum Type { } private T value; private List<Type> types = new ArrayList<>(); public T getValue() { return value; } public
public class HelloWorld<T> {
private static enum Type {
}
private T value;
private List<Type> types = new ArrayList<>();
public T getValue() { return value; }
public List<Type> getTypes() { return types; }
public static void main( String[] args ) {
for ( Type type : new HelloWorld().getTypes() ) { // Error: Type mismatch: cannot convert from element type Object to HelloWorld.Type
}
}
}
公共类HelloWorld{
私有静态枚举类型{
}
私人T值;
私有列表类型=新的ArrayList();
公共T getValue(){return value;}
公共列表getTypes(){return types;}
公共静态void main(字符串[]args){
对于(类型类型:new HelloWorld().getTypes()){//错误:类型不匹配:无法从元素类型对象转换为HelloWorld.Type
}
}
}
为什么getTypes()
返回一个对象
(原始)列表,而它应该类型
列表
更改
for
循环,为类添加泛型类型:
例如:我刚才用“Type
”作为例子
for ( Type type : new HelloWorld<Type>().getTypes() ) {
for(类型:new HelloWorld().getTypes()){
编辑:
它可以是“字符串”,也可以是在评论中指出的(谢谢)。
在您的情况下,它应该是该类所需的实际类型
其想法是缺少需要添加的泛型类型。在
main
方法中:
for ( Type type : new HelloWorld().getTypes() ) {//Here also you did not mention the type for the new object since
}
尝试以下主要方法:
for ( Type type : new HelloWorld<Type>().getTypes() ) {
}
for(类型:new HelloWorld().getTypes()){
}
这在我看来像是编译器的限制。getTypes
总是返回一个列表
,因此使用原始HelloWorld
类型应该没有什么区别
也就是说,这两种解决方案中的任何一种都可以克服错误:
HelloWorld.java:10: error: incompatible types: Object cannot be converted to Integer
Integer hello = new HelloWorld().getTest().getT();
^
1 error
HelloWorld
的参数化类型,而不是原始类型:
for (Type type : new HelloWorld<Integer>().getTypes() ) { // any type will do, I chose
// Integer arbitrarily to show
// that it doesn't matter
}
for(类型:newhelloworld().getTypes()){//我选择了任何类型都可以
//任意整数表示
//没关系
}
List<Type> types = new HelloWorld().getTypes();
for (Type type : types) {
}
List types=new HelloWorld().getTypes();
对于(类型:types){
}
无论如何,参数化类型应始终优先于原始类型,因此我将使用第一种解决方案(使用类中有意义的任何类型参数)。在试验代码时,我注意到一些非常有趣的问题。为了消除编译器错误: 错误:类型不匹配:无法从元素类型对象转换为 HelloWorld.Type 由于它声明返回的元素的类型为
Object
I决定将其类型转换为List
,如下所示:
public static void main( String[] args ) {
for ( Type type : (List<Type>)new HelloWorld().getTypes() ) {
}
}
在这里,我惊讶地看到第二个警告。它指出required是List
,但找到List
aRAW TYPE。因此,这意味着如果初始化RAW TYPE对象并调用返回具有泛型的变量的方法,该变量也将转换为RAW TYPE,以便进行测试我实现了一个类HelloWorldTest
,如下所示:
public class HelloWorldTest<T>{
private T t;
public HelloWorldTest(T t){
this.t = t;
}
public T getT(){
return t;
}
}
因此,这里我们还发现,HelloWorldTest
已被转换为原始类型
最后,我们可以推断:如果初始化一个原始类型对象并调用一个返回具有泛型的变量的方法,该变量也将转换为原始类型
现在当我替换
HelloWorldTest<Integer> hello = new HelloWorld().getTest();
正如所料,我得到了错误:
HelloWorld.java:10: error: incompatible types: Object cannot be converted to Integer
Integer hello = new HelloWorld().getTest().getT();
^
1 error
最后,如果将我实现的HelloWorld
类中的main方法替换为:
public static void main( String[] args ) {
String hello = (String) new HelloWorld().getTest().getT();
}
它成功编译,唯一的警告是:
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:10:警告:[rawtypes]找到原始类型:HelloWorld
String hello=(String)new HelloWorld().getTest().getT();
^
泛型类HelloWorld缺少类型参数
其中T是一个类型变量:
T扩展类HelloWorld中声明的对象
1警告
这是相当误导的,因为这肯定会遇到运行时错误,并再次说明了泛型中原始类型的危险。…您链接到了联机编译器,但没有读取其输出?
HelloWorld.java:17:error:不兼容类型:对象无法转换为类型。
是它给出的错误。我看到了错误。为什么会发生这种情况?getTypes()没有使用泛型类型参数。方法的返回类型是显式设置的。“type”是私有的,“getTypes”公开返回这些私有对象的列表,除了我之外没有人会受到它的影响?您已经声明了泛型类HelloWorld
,并在没有参数的情况下初始化了它:newhelloworld()
虽然这个答案可能是正确的,但您还应该解释为什么会出现错误以及为什么您的答案会修复它。这将对OP有更大的帮助。泛型类型参数T在getTypes
方法中的任何地方都没有使用,所以为什么它会有关系呢?getTypes
应该返回一个列表,而不管泛型类型参数是什么(new HelloWorld().getTypes()
仍应返回列表
)。我建议使用new HelloWorld
而不是new HelloWorld
,因此getTypes()方法将返回object类型的对象
-为什么?公共列表getTypes(){返回类型;}
-总是返回列表
。为什么它会返回对象
?这很有趣!我在IDE中尝试过它,当我实例化新HelloWorld()
(原始类型)时,整个类型都是原始的。因此,getTypes()
突然返回一个原始的列表
。这是一个有趣的行为,也是一个永远不要使用原始类型的原因!当你声明了列表
之后,就没有必要将类型
添加到数组列表
初始化中。是的,当然。但在代码中,他添加了类似新数组列表()
。这应该是new ArrayList()
或new ArrayList()
。不是吗?否则这一行的多个标记将出错-'
HelloWorld.java:10: error: incompatible types: Object cannot be converted to Integer
Integer hello = new HelloWorld().getTest().getT();
^
1 error
public static void main( String[] args ) {
String hello = (String) new HelloWorld().getTest().getT();
}
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