Reference Type Conversions
Objects can be converted between different reference types. As with primitive types,
reference type conversions can be widening conversions (allowed automatically by
the compiler) or narrowing conversions that require a cast (and possibly a runtime
check). In order to understand reference type conversions, you need to understand
that reference types form a hierarchy, usually called the class hierarchy .
Every Java reference type extends some other type, known as its superclass . A type
inherits the fields and methods of its superclass and then defines its own additional
fields and methods. A special class named Object serves as the root of the class
hierarchy in Java. All Java classes extend Object directly or indirectly. The Object
class defines a number of special methods that are inherited (or overridden) by all
The predefined String class and the Point class we discussed earlier in this chapter
both extend Object . Thus, we can say that all String objects are also Object objects.
We can also say that all Point objects are Object objects. The opposite is not true,
however. We cannot say that every Object is a String because, as we've just seen,
some Object objects are Point objects.
With this simple understanding of the class hierarchy, we can define the rules of ref‐
erence type conversion:
• An object cannot be converted to an unrelated type. The Java compiler does
not allow you to convert a String to a Point , for example, even if you use a
• An object can be converted to the type of its superclass or of any ancestor class.
This is a widening conversion, so no cast is required. For example, a String
value can be assigned to a variable of type Object or passed to a method where
an Object parameter is expected.
No conversion is actually performed; the object is simply
treated as if it were an instance of the superclass. This is some‐
times referred to as the Liskov substitution principle, after
Barbara Liskov, the computer scientist who first explicitly for‐
• An object can be converted to the type of a subclass, but this is a narrowing
conversion and requires a cast. The Java compiler provisionally allows this kind
of conversion, but the Java interpreter checks at runtime to make sure it is
valid. Only cast an object to the type of a subclass if you are sure, based on the
logic of your program, that the object is actually an instance of the subclass. If
it is not, the interpreter throws a ClassCastException . For example, if we
assign a String object to a variable of type Object , we can later cast the value
of that variable back to type String :