For this kind of purpose, it is useful to distinguish between the type of variable set in its declaration and the class of the object created when the object was created.
The variable is allowed to be null
or point to any object whose class corresponds to its type, or is a direct or indirect subclass of this class. Because String
is a subclass of Object
, a variable of type Object
can point to an object of class String
.
In your example, the compiler knows that the String
expression must be null
or point to a String
object, so at compile time Object o = new String("Hello");
.
On the other hand, an expression or variable of type Object
may refer to String, but may refer to something completely different. The compiler requires an explicit cast to say that the conversion is in order.
public class Test { public static void main(String[] args) { Object stringObject = "xyzzy"; Object integerObject = new Integer(3); String test1 = (String)stringObject; System.out.println(test1); String test2 = (String) integerObject; System.out.println(test2); } }
This program compiles because I told the compiler that the conversions are ok with my clicks. It goes through the first call to println
because stringObject
really points to String
. It fails with a ClassCastException
on the line String test2 = (String) integerObject;
. As far as the compiler knows, integerObject
can point to a String
, so it took my action. At run time, the JVM finds that it really points to Integer
and throws an exception.
Using the Object
type for integerObject is significant. This does the conversion String test2 = (String) integerObject;
expressions of type Object for type String, a conversion that can be successful, depending on what integerObject
actually refers to. If integerObject
declared type Integer
, the compiler would reject the program. There are no objects that Integer
and String
expressions can reference.
source share