Each object has two types: 1) The type of its reference variable, and 2) its actual type.
In the code example that you gave, the object reference variable, "animal" refers to an object of type "Animal". You cannot cast this object to a Dog type because its actual type is Animal.
The object referenced by the variable "animal" has two types: 1) Object and 2) Animal.
The error is not caught at compile-time because some Animal objects are of type Dog. In general, the compiler checks line-by-line and tries to find as many errors as it can at compile-time but the compiler doesn't do any computations so some errors show up at runtime and an exception or an error is thrown at runtime instead of a compile-time error occurring. [ September 12, 2007: Message edited by: Kaydell Leavitt ]
Leftside is checked at Compile Time. Rigthside checked at Runtime .......
Not quite. The variable gets a type once and for all to know what methods or fields can be used on objects of the type. But what the object really is (the right side) can only partially be checked by the compiler.
The compiler only looks, if the type hierarchy is ok, e.g. it won't let you assign a String to an Animal variable.
But when these are ok, the rest happens at runtime, because you can easily assign subclasses to yor variable. Or implementers if the variable has got an Interface type.
Here's an example for assigning objects of different subtype at runtime, for those who are bored of animals. :
At compile time the compiler does not know exactly what subtype will be assigned as element of the array. Compiler only checks, if it really is a subtype of Planta (or Planta itself). But the object type will be known only at runtime.
output e.g. like I am a Bougainvillea I am a Planta I am a Planta I am a Conium and I'm poisonous I am a Magnolia I am a Bougainvillea I am a Magnolia I am a Bougainvillea I am a Bougainvillea I am a Bougainvillea
Originally posted by Kaydell Leavitt: Each object has two types: 1) The type of its reference variable, and 2) its actual type...
Hmmm... Be careful with this wording.
An object has a true runtime type, determined by what constructor was used with "new." It also has supertypes (unless the true runtime type happens to be the base class, java.lang.Object). In this sense, an object can have many types.
A reference also has a type, which must be the type of the object it's pointing to, or any of that object's supertypes.
So rather than talking about the "object" having "two" types, I think it's important to distinguish between the reference type and the object's true runtime type.
"We're kind of on the level of crossword puzzle writers... And no one ever goes to them and gives them an award." ~Joe Strummer sscce.org