Casting and Converting Reference Types

   

Classes and arrays are known as reference types in Java. These types are always handled with references. Unlike C/C++, you cannot dereference an object to work with it by value instead. When you are using reference types, it is often necessary to cast or convert an object to another type.

One strength of inheritance is that you can treat an instance of a subclass the same as an instance of its parent class. You typically see this when you pass an object to a method that expects a parameter whose type is that of the object's superclass. This might look like a parameter mismatch in your code but the compiler automatically handles the use of a subclass in place of one of its superclasses by converting the reference. This is not true when you attempt to use a reference declared to be of a superclass type as one of its subclasses. In this case, you need to explicitly cast the reference to the expected type as shown in the following:

 public void myMethod(MyParentClass myObject) {   if (myObject != null) {     MySubClass childInstance = (MySubClass)myObject;     childInstance.specialMethod();   } } 

Compile-Time Versus Runtime Type Checking

If you look carefully at the preceding example, you will notice that there is nothing in place to guarantee that myObject really refers to an instance of MySubClass. Why does the compiler allow this? The answer lies in the difference between compile-time and runtime type checking. In this example, although it is possible that myObject does not refer to the correct instance type, it is also possible that it does. The compiler trusts you to provide a correct instance and thus defers type checking to runtime when the cast is actually performed. If myMethod is called with an instance that is not a MySubClass, the cast operation will cause a ClassCastException.

Using the instanceof Operator

The instanceof operator allows you to check the class of an object during execution of your program. This operator is commonly used before a cast is performed to ensure that the cast will not throw an exception. For example, here is a safer version of MyMethod:

 public void myMethod(MyParentClass myObject) {   // perform an operation if the object passed to the method is      // an instance of a particular subclass   if (myObject instanceof MySubClass) {     // myObject is a MySubClass instance, so this cast is safe     MySubClass childInstance = (MySubClass)myObject;     childInstance.specialMethod();   } } 

Caution

The instanceof operator is useful but you should not use it excessively. If you find yourself coding instanceof conditionals in many of your methods , you should probably re-evaluate your class design. In the preceding example, myMethod would be cleaner and easier to maintain if specialMethod were defined in MyParentClass with a do-nothing implementation (it could also be abstract if MyParentClass happened to be abstract already). The MySubClass implementation of the method would then be an override. With this change, myMethod would no longer need to implement special behavior based on the specific subclass type. You could call specialMethod directly on myObject and polymorphism would take care of the rest. Behavior like that in the original myMethod implementation is sometimes necessary, but it is difficult to maintain a method that might need to be updated whenever a new subclass is defined.


   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net