Reputation: 169
I have just started learning java and I have two basics questions. My main() looks like this:
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 ) {
}
}}
Why do I get these errors:
After that I tried to replace:
Object myAccount = baCls.newInstance();
with
BankAccount myAccount = baCls.newInstance();
But then I am getting this error:
I know that the right way would be:
BankAccount myAccount = (BankAccount) baCls.newInstance();
But I am not really sure that I understand why... I tried to read about it from a various sources so I have a few theories, but I still cannot wrap my head around this properly. Can someone please help me understand?
P.S. Sorry for posting such a basic question.
Upvotes: 1
Views: 6505
Reputation: 13956
Doing BankAccount myAccount = baCls.newInstance()
invokes reflection to create a new object. Class
is generic, but you have not specified the generic type. If you do Class<BankAccount> baCls = BankAccount.class
then you shouldn't need to cast.
Java is strongly typed. By declaring an object as object
you're saying to the language that this object is just an object: that is it only has the methods and fields found on ALL objects, and nothing more.
By specifying the type, you tell Java what methods and fields you can access, which is why when you write BankAccount myAccount
, it allows you to call functions on it.
But baCls.newInstance()
creates a new instance of whatever class baCls is. It doesn't know what type of class it is creating since it's a method on the Class class (confusing) itself, so you have to tell Java what class you expect it to return via casting: BankAccount myAccount = (BankAccount) baCls.newInstance();
However, the bigger question is why you are using newInstance
in the first place. Is it possible to do:
BankAccount myAccount = new BankAccount();
Reflection is a little advanced for a beginner.
Upvotes: 9
Reputation: 6473
Because you've defined it via the Object interface, which doesn't know about your object specific methods, such as deposit().
Object myAccount = baCls.newInstance();
Should be...
BankAccount myAccount = (BankAccount)(baCls.newInstance());
Or simply...
BankAccount myAccount = new BankAccount();
Then you can call deposit on it, as that exists in the contract defined by BankAccount, assuming that baCls is indeed a BankAccount. You can check this with instanceof BankAccount
beforehand, if you're uncertain of its type.
By way of further explanation...
If I define a class of OperatingSystem
, then I subclass that class to be UnixOperatingSystem
and WindowsOperatingSystem
. Now, obviously there are things that are common, but also specific to each of these computers. But if I do this...
OperatingSystem os = new WindowsOperatingSystem();
Then, I am creating a WindowsOperatingSystem, but only allowing the common OperatingSystem methods to be called, as that's what's defined in that super class by its method signature contract. I could therefore call the shutdown()
method perhaps (as any OS should be able to shutdown), but not the runBatchFile("test.bat")
method. I would need to declare it explicitly as a WindowsOperatingSystem to be able to call that specific method.
Upvotes: 2