2016-04-15 32 views
0

我刚开始学习java,我有两个基本问题。 我的main()看起来是这样的:使用“Object”关键字在Java中创建对象

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) { 
    } 
}} 

为什么我得到这些错误:

  • 的方法存款(INT)是未定义的类型对象
  • 的方法SetValue(的BankAccount)在类型Storage中不适用于参数(Object)。

之后,我试图取代:

Object myAccount = baCls.newInstance(); 

BankAccount myAccount = baCls.newInstance(); 

但后来我得到这个错误:

  • 类型不匹配:不能从对象转换为BankAccount

我知道,正确的方法是:

BankAccount myAccount = (BankAccount) baCls.newInstance(); 

但我真的不知道,我明白为什么... 我试图从各种渠道了解,所以我有几个理论,但我仍然无法适当地将我的头围绕在上面。 有人可以帮我理解吗?

P.S. 对不起,发布这样一个基本的问题。

+5

是否有你试图通过使用Object#newInstance而不是像'BankAccount myAccount = new BankAccount()'这样的东西实例化的原因? – Exupery

+1

没有任何特定的原因,我只是在试图理解该语言的基本概念:) – Cooli

回答

7

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。是否可以这样做:

反射对于初学者来说有点高级。

+1

一个微妙的但重要的点:你并不是说对象具有所有对象的方法和字段,仅此而已。你说它有对象上的所有方法沙场,我们不知道它可能有什么。如果你下载引用来获取这些额外的方法和字段,那么底层对象就完全没有改变 - 它不会突然“获取”它以前没有的方法和字段。所有这些变化都是编译者对这些成员的了解。 – yshavit

+0

非常感谢Jason。我知道 BankAccount myAccount = new BankAccount(); 将是最好的方法,我只是想玩弄一下,理解一些Java的基本概念。 对于myAccount发生什么情况,我仍然有点困惑: BankAccount myAccount = baCls.newInstance(); – Cooli

+3

正在执行'BankAccount myAccount = baCls.newInstance()'调用反射来创建一个新对象。类是通用的,但是你没有指定泛型类型。如果你做'Class baCls = BankAccount.class',那么你不需要投。 – Jason

1

因为你已经通过Object接口定义了它,它不知道你的对象的具体方法,比如deposit()。

Object myAccount = baCls.newInstance(); 

应该是...

BankAccount myAccount = (BankAccount)(baCls.newInstance()); 

或者干脆...

然后你就可以调用它的存款,作为由定义的BankAccount合同存在,假设baCls确实是BankAccount。如果您不确定其类型,您可以事先与instanceof BankAccount进行核对。

通过进一步的解释...

如果我定义一个类的OperatingSystem,然后我子类化类是UnixOperatingSystemWindowsOperatingSystem。现在,显然有些事情是常见的,但也是特定于每台计算机的。但是,如果我这样做...

OperatingSystem os = new WindowsOperatingSystem(); 

然后,我创建一个WindowsOperatingSystem,但只允许普通OperatingSystem的方法被调用,因为那正是它的方法签名的合同在超类中定义。因此,我可能会调用shutdown()方法(因为任何操作系统应该能够关闭),但不能使用runBatchFile("test.bat")方法。我需要将其明确声明为Windows操作系统才能调用该特定方法。

相关问题