I encountered a question in school which asked for the the kind of typecasting and whether an error would occur.
InterfaceA obj = new ClassB();
ClassA obj2 = obj;
I understand that the first line would cause a compile time error due to ClassB being abstract. However, would the 2nd line upcasting from, an actual object type ClassB with object reference InterfaceA, to ClassA work? (if ClassB is not abstract)
Given the following UML class diagram:
It wouldn't compile; an object that is guaranteed to be of type InterfaceA
is not guaranteed to also neccessarily be of type ClassA
. Even if ClassB
is the only class available that implements InterfaceA
at the time you wrote this code (code isn't set in amber; maybe someone writes another class later).
But, add the cast, and sure, it would.
This:
InterfaceA obj = new ClassB();
is creating 2 completely unrelated things. A local variable named obj
, which is like a postit note with a title that you can write addresses on. The postit note is restricted; you can only write addresses on there that lead to houses with a red roof. (Let's say that's what InterfaceA
represents).
You then, separately, build a house. Houses don't have names. This house does have a red roof (the class you are instantiating implements InterfaceA
). You then scribble the address of this newly built house on your postit, and that's okay - after all, it has a red roof.
The house has no idea about the postit and doesn't care. The post-it's existence doesn't change the house, at all. It is not possible to go to the house and then ask the house: Can you tell me the locations of all postits with your address on it worldwide. In java terms: Having a variable point at an object doesn't modify that object in any way, it is not possible to go from an object to the variable(s) that refer to it, at all.
You then do:
ClassA obj2 = obj;
This creates another titled postit. It's titled 'obj2', and it is restricted to only allow address to brick-built houses to be written on there.
You then attempt to take your obj
postit (restricted to only have addresses to houses with a red roof), and copy over the address onto your new postit. You're certainly not creating a second house (new
needs to be involved in java if you want another object to be created), you're just copying over an address.
The postit note police stops you though: Whilst the address on your obj
postit might be brick-built, it may not be; the obj
postit can merely guarantee that the roof is red, not that it is built from bricks.
With a cast operation:
ClassA obj2 = (ClassA) obj;
The code now compiles (and if you were to run it and remove the abstract
modifier from ClassB
, it would run successfully). A cast operation merely checks, it doesn't change any roofs or otherwise convert anything at all. That code will drive out to the house, check that it is brick-built.
If it is, great, you get to copy over the address. If it is not, a ClassCastException is thrown.
In no scenario will a cast operator convert anything, unless the thing in the ()
is a primitive type (the cast operator does 3 completely different things: Convert primitives, typecheck concrete types, and tell the compiler to shut up for generics without checking anything).