I'm no really sure how to explain my doubt right away, so I'll start with an example. I have the next lines:
Object myObject = null;
Integer myInteger = 10;
myObject = myInteger;
Basically, I know I can assign one subclass object to a superclass object (in this scenario, myInteger of type Integer
to myObject of type Object
). So far so good, but now... let's say I want to get the class of myObject.
System.out.println("myObject: " + myObject.getClass());
And it prints this:
myObject: class java.lang.Integer
It says is of type Integer
!
I know a variable actually stores a reference to the actual object in memory, so the method getClass()
is returning the class of the actual object. But then...
Why can't I access the methods of the class Integer
through myObject since is pointing to an object of type Integer
? I mean, why can't I do something like this? myObject.intValue();
If I can only access to the methods of Object
through myObject (even though it's pointing to an object of type Integer
), how does Java know which methods can be called through myObject? the variable itself stores a type of class?
Basically, I would like to know what information Java stores in the variables, is it only a reference? or it also has a class name? how the variable know which methods can be called if it has assigned a reference to a subclass object?
I hope my doubt is clear, and excuse my grammar.
Consider this analogy: you provide storage services with three tiers of "safety level": General goods, Valued items, and Luxury items. You have an online system that lets your clients book space and make payments based on what they want to store. Depending on the tier, your services and booking requirements are different:
General goods:
Valued items:
Luxury items:
Now, consider that your clients bring items in boxes marked with a reference number issued by your reservation system and your security guards on location inspect the content.
Let's see what your process steps do:
Online system:
Security guards:
What do you think of these scenarios?
So it is with Java (roughly speaking):
In other words, the online system is like the compiler, and the physical location is like the runtime.
In Java, the type of tier you reserved online is known as "static type", it's the type known at compile-time (at booking time). The actual type you put in the box is known as the "runtime class", being dynamic (just as a general goods tier box can be allowed to take in gold, or a mid, valued item like a TV).
Just as with the box, only the runtime knows the actual/runtime class of the variable: only the staff on-site will know that it's gold in the box. And when you call myObject.getClass()
, that's exactly what you're asking for: the runtime class of myObject
(this is the class whose constructor is called or with which new
is used; or in some cases, the class of the literal, such as 10
for int
or Integer
, but this is a story for another day). But even if at runtime it's known to be an Integer
, the compiler (online system, remember?) won't let you call methods that are on Integer
because myObject
was declared as Object
: the online system won't let you see video footage of a general goods booking even if the box holds diamond. You can force the compiler to accept Integer
's methods on myObject
with a type cast, as shown in Sweeper's good answer, and this is a little like upgrading to luxury items on site, after which the online system will let you get higher tier services :)
This analogy is possibly ridiculous in some aspects, such as in the fact that the compiler prevents you from assigning an incompatible or broader-typed value to a variable... but it's just an example, a limited one.