我有一个基本的java问题,因为我最近决定深入研究这门语言(我一直专注于C ++很长一段时间,并决定稍微扩展我的视野)。
假设我有一个名为BankAccount的类,我尝试在main中创建和对象,有什么区别:
Class baCls = BankAccount.class;
和
Class<BankAccount> baCls = BankAccount.class;
每个案例中baCls的含义是什么?编译器输出是什么?
答案 0 :(得分:4)
在这两种情况下,baCls
都是对类BankAccount
泛型添加了编译时检查,但在运行时没有影响。
如果在IDE中使用javap -c -p
或字节代码查看器,则可以看到生成的字节码。
答案 1 :(得分:0)
Peter Lawrey的回答解决了您的具体问题,但我认为它缺少一个重要的事实,即第二个案例为编译器提供了额外的宝贵信息。
不同之处在于第一种情况是原始类型:
Class baCls = BankAccount.class;
^ Missing type parameters.
这有(至少)两种后果(这是使用原始类型的一般后果):
您无法调用Class.nextInstance()
方法之类的生产者方法,并将结果分配给类型为BankAccount
的引用而不进行强制转换:
Class baCls = BankAccount.class;
BankAccount instance = (BankAccount) baCls.newInstance(/* required args */);
但是,在第二种情况下,您不需要演员,因为已知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.
我建议您阅读有关原始类型的内容,例如:在generics tutorial,以及 Effective Java 2nd Ed 项目23&#34;不要在新代码中使用原始类型&#34;。