Class and interface

A variable of a class type is declared using the corresponding class name:

<Class name> identifier;

The value that can be assigned to such a variable can be one of the following:

This last type of assignment is called a widening assignment because it forces a specialized reference to become less specialized. For example, since every Java class is a subclass of java.lang.Object, the following assignment can be done for any class:

Object obj = new AnyClassName();

Such an assignment is also called a upcasting because it moves the type of the variable up on the line of inheritance (which, like any family tree, is usually presented with the oldest ancestor at the top).

After such an upcasting, it is possible to make a narrowing assignment using a cast operator (type):

AnyClassName anyClassName = (AnyClassName)obj;

Such an assignment is also called a downcasting and allows you to restore the descendant type. To apply this operation, you have to be sure that the identifier refers to a descendant type in fact. If in doubt, you can use the instanceof operator (see Chapter 2, Java Object-Oriented Programming) to check the reference type.

Similarly, if a class implements a certain interface, its object reference can be assigned to this interface or any ancestor of the interface:

interface C {}
interface B extends C {}
class A implements B { }
B b = new A();
C c = new A();
A a1 = (A)b;
A a2 = (A)c;

As you can see, as in the case with class reference upcasting and downcasting, it is possible to recover the original type of the object after its reference was assigned to a variable of one of the implemented interfaces types. 

The material of this section can also be viewed as another demonstration of Java polymorphism in action.