我刚刚开始学习java,我有两个基本问题。 我的main()看起来像这样:
public class Main {
public static void main(String[] args) {
Storage<BankAccount> aStorage = new Storage<BankAccount>();
Storage<String> sStorage = new Storage<String>();
Class baCls = BankAccount.class;
try {
Object myAccount = baCls.newInstance();
aStorage.setValue( myAccount );
myAccount.deposit( 15 );
}
catch ( InstantiationException e ) {
}
catch ( IllegalAccessException e ) {
}
}}
为什么我会收到这些错误:
之后我试图替换:
Object myAccount = baCls.newInstance();
与
BankAccount myAccount = baCls.newInstance();
但后来我收到了这个错误:
我知道正确的方法是:
BankAccount myAccount = (BankAccount) baCls.newInstance();
但我不确定我明白为什么...... 我尝试从各种来源阅读它,所以我有一些理论,但我仍然无法正确地理解这一点。 有人可以帮我理解吗?
P.S。 很抱歉发布了这样一个基本问题。
答案 0 :(得分:9)
执行BankAccount myAccount = baCls.newInstance()
调用反射来创建新对象。 Class
是通用的,但您尚未指定泛型类型。如果你做Class<BankAccount> baCls = BankAccount.class
那么你就不需要施放。
Java是强类型的。通过将对象声明为object
,您对语言说这个对象只是一个对象:就是它只有在所有对象上找到的方法和字段,仅此而已。
通过指定类型,您可以告诉Java您可以访问哪些方法和字段,这就是为什么当您编写BankAccount myAccount
时,它允许您在其上调用函数。
但是baCls.newInstance()
创建了一个baCls类的新实例。它不知道它正在创建什么类型的类,因为它是Class类上的一个方法(令人困惑)本身,所以你必须告诉Java你希望它通过转换返回什么类:BankAccount myAccount = (BankAccount) baCls.newInstance();
然而,更大的问题是您首先使用newInstance
的原因。是否可以这样做:
BankAccount myAccount = new BankAccount();
初学者的反思有点先进。
答案 1 :(得分:2)
因为您已经通过Object界面对其进行了定义,而Object界面并不了解您的对象特定方法,例如deposit()。
Object myAccount = baCls.newInstance();
应该......
BankAccount myAccount = (BankAccount)(baCls.newInstance());
或者只是......
BankAccount myAccount = new BankAccount();
然后,您可以在BankAccount定义的合同中调用存款,假设baCls确实是BankAccount。如果您不确定其类型,可以事先使用instanceof BankAccount
进行检查。
进一步解释......
如果我定义了一个OperatingSystem
类,那么我将该类子类化为UnixOperatingSystem
和WindowsOperatingSystem
。现在,显然有一些常见的东西,但也特定于每台计算机。但如果我这样做......
OperatingSystem os = new WindowsOperatingSystem();
然后,我正在创建一个WindowsOperatingSystem,但只允许调用常见的OperatingSystem方法,因为它通过方法签名契约在超类中定义了什么。因此,我可以调用shutdown()
方法(因为任何操作系统都应该能够关闭),而不是runBatchFile("test.bat")
方法。我需要将它明确声明为WindowsOperatingSystem才能调用该特定方法。