繁体   English   中英

有关泛型和反射的Java基础知识

[英]Java basics about generics and reflection

最近我决定深入研究Java语言时,我遇到了一个基本的Java问题(我一直在专门从事C ++的工作,并决定扩大自己的视野)。

假设我有一个名为BankAccount的类,并且尝试在主类中创建和对象,两者之间有什么区别?

Class baCls = BankAccount.class; 

Class<BankAccount> baCls = BankAccount.class;

baCl在每种情况下都具有什么作用,编译器的输出是什么?

在这两种情况下, baCls都是对BankAccount类的引用

泛型添加了编译时检查,但对运行时没有影响。

如果在IDE中使用javap -c -p或字节码查看器,则可以看到生成的字节码。

彼得·劳瑞(Peter Lawrey)的回答解决了您的特定问题,但我认为它缺少一个重要的事实,即第二种情况为编译器提供了额外的宝贵信息。

区别在于,第一种情况是原始类型

Class baCls = BankAccount.class;
     ^ Missing type parameters.

至少有两个结果(这是使用原始类型的一般结果):

  1. 您不能调用诸如Class.nextInstance()方法之类的生产者方法,并将结果分配给类型为BankAccount的引用,而不能进行Class.nextInstance()

     Class baCls = BankAccount.class; BankAccount instance = (BankAccount) baCls.newInstance(/* required args */); 

    但是,在第二种情况下不需要nextInstance ,因为已知nextInstance方法将返回BankAccount一个实例:

     Class<BankAccount> baClsSafe = BankAccount.class; BankAccount instance = baCls.newInstance(/* req args */); 
  2. 如果将这些放入集合中,则会失去类型安全性。 例如:

     Class baCls = BankAccount.class; List<Class<String>> list = new ArrayList<>(); list.add(baCls); // Compiles fine. 

    这看起来不错,但是如果您假定列表中的元素属于正确的类型,则稍后会出现运行时异常:

     for (Class<String> clazz : list) { String instance = clazz.newInstance(); // ClassCastException. } 

    因为instance实际上是BankAccount的实例(假设它具有零参数构造函数)。

    在第二种情况下,您将永远无法首先将此项目添加到列表中:

     Class<BankAccount> baCls = BankAccount.class; List<Class<String>> list = new ArrayList<>(); list.add(baCls); // Compiler error. 

我建议您阅读原始类型,例如在泛型教程中以及在有效的Java 2nd Ed项目23“不要在新代码中使用原始类型”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM