[英]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.
至少有两个结果(这是使用原始类型的一般结果):
您不能调用诸如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 */);
如果将这些放入集合中,则会失去类型安全性。 例如:
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.