【问题标题】:Initializing generic type fields in the class itself在类本身中初始化泛型类型字段
【发布时间】:2020-04-22 08:16:11
【问题描述】:

这里是代码...

public class Dog {

}


public class Bird {

}


public class Animal< T > {
    T field1 = (T) new Bird();  // unchecked cast : Bird to T

    public void display() {
        System.out.println(field1);
    }
}

我期待运行时错误,但它运行良好....

它给了我输出:

com.company.Bird@48140564

在主类中

public static void main(){
    Animal<Dog> animal = new Animal();
    animal.display();   // I was expecting run time error here

}

【问题讨论】:

  • 问题是什么?您面临什么问题?
  • 这正是“unchecked cast”警告告诉你的,这个构造的有效性不会在运行时被检查。一些构造可能会失败,而另一些则不会,这使得这很成问题。它可能在远离最初发生堆污染的代码的地方失败。

标签: java class generics field instance


【解决方案1】:

它没有出错,因为代码仍然“有效”。 Java 泛型是一种处理对象强制转换和改进类型检查的好方法。每次使用泛型时,在编译代码时,Java 都会将它们转换为显式转换。主要原因与引入泛型之前的 Java 版本有关,因此 Java 像“对象”类一样处理它们,然后在需要时为您转换它们。

例如,在您的 .java 文件中编写以下代码:

String hello = new String();
ArrayList<String> list = new ArrayList<>();
list.add(hello);

Object noCastRequired = list.get(0);
String castRequired = list.get(0);

在其相关的 .class 文件中,Java 将编写:

String hello = new String();
ArrayList<String> list = new ArrayList();
list.add(hello);
Object noCastRequired = list.get(0);
String castRequired = (String)list.get(0);

如果你要检查你的编译代码,你可以看到这个表达式仍然是一个有效的代码语句,但是如果你尝试在一个方法中“使用”那个字段,你就会遇到错误和麻烦“类型”是必需的; print 语句接受对象类的参数,因此 Java 不会强制转换它。

例子:

class Scratch {
    public static void main(String[] args) {
        Root<FirstLevel> correct = new Root<>();

        Root<FirstLevelChild> iAmNotValid = new Root<>(); // No error
        Root<SecondLevel> iAmNotValidToo = new Root<>(); // No error

        System.out.println(correct.field.first); // Ok
        System.out.println(iAmNotValid.field.first); // Ko, because java.lang.ClassCastException: FirstLevel cannot be cast to FirstLevelChild
        System.out.println(iAmNotValidToo.field.second);
    }


}

class Root<T> {
    public T field = (T) new FirstLevel();
}

class FirstLevel {
    public String first = "First";
}

class SecondLevel {
    public String second = "Second";
}

class FirstLevelChild extends FirstLevel {
}

【讨论】:

  • 好的,所以在您的 Root 类中,“new FirstLevel()”被强制转换为 T。这是什么意思。假设在主类中,如果您将实际参数作为与您的 FirstLevel 类不相关的其他类提供,那么它不应该给我错误。
  • 当你提供一个与FirstLevel无关的类,如Root,代码仍然可以编译,因为Java会将T转换成Object,所以T field = (T) new FirstLevel( ) 将是 Object field = new FirstLevel()。当我要使用需要 T 类型的“字段”时,将抛出 ClassCastException,因为 Java 将放入 .class 文件(SecondLevel)字段。即使您使用与 FirstLevel 相关的类(如 FirstLevelChild)也会引发此运行时错误,因为字段将始终为“FirstLevel”对象,因此 (FirstLevelChild) 字段不是有效的转换。
  • 非常感谢;你能给我提供链接,以便我可以阅读更多相关信息。这对我很有帮助。; :)
  • 您可以阅读angelikalanger.com/GenericsFAQ/FAQSections/… 或任何Oracle Java 参考书
  • @sparshgoyal 这个答案对你有帮助吗?
猜你喜欢
  • 2019-10-06
  • 1970-01-01
  • 2019-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多