Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么这段代码不是';不可编译_Java_Generics - Fatal编程技术网

Java 为什么这段代码不是';不可编译

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

这里是一小段代码,我不明白为什么javac不能编译它。我想念什么?有什么错误吗

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