| Here we look at other aspects of working with classes . In Chapter 2 we discussed the topic of mixing 
              different primitive types in the same operation and the need in 
              some cases to explicitly cast 
              one type into another. An object reference can also need casting. 
              However, it can only cast to its own class type or to one of its 
              sub- or super-classes types or interfaces.  Automatic Conversions Sometimes, as with primitives, the type conversion 
              is automatically handled by the compiler. Consider a superclass 
               Fruit 
              with a subclass Pineapple: 
               class 
              Fruit { ... } class Pineapple extends Fruit { ... }
  Let f 
              be a variable of type Fruit 
              and p be 
              of type Pineapple. 
              Then we can assign the Pineapple 
              reference to the Fruit 
              variable:  
              
                 
                  | class 
                    Conversion { Fruit f;
 Pineapple p;
 public void convert () {
 p = new Pineapple ();
 f = p;
 }
 }
 |    The compiler automatically handles the assignment 
              since the types are compatible. That is, the type Fruit 
              can "hold" the type Pineapple 
              since a Pineapple 
              is a Fruit. 
              Such automatic cases are called conversions.  A related automatic conversion is with interfaces. 
              Let the class Fruit 
              implement the Sweet 
              interface.     interface 
              Sweet { ... } class Fruit implements Sweet { ... }
 Then we see that a variable of type Fruit 
              can be automatically converted to a variable of type Sweet. 
              This makes perfect sense since a Fruit 
              is Sweet.    Fruit 
              f; Sweet s;
 public void good_convert () {
 s = f; // legal conversion from class type to 
              interface type
 }
 However, an attempt to convert from the interface 
              type to the class type does not compile:    public 
              void bad_convert () { f = s; // illegal conversion from interface type 
              to class type
 }
 Explicit Casts For cases where automatic conversion does not apply, 
              an explicit cast is required. As with casting primitive types, the 
              class type that an object is being cast to is enclosed in parenthesis 
              in front of the object reference. For example, let the classes BClass 
              and CClass 
              be subclasses of AClass. 
                class 
              AClass {void 
              aMethod () { ... }
 }
   class 
              BClass extends AClass { void bMethod () { ... }
 }
 In some other class there is miscMethod(AClass 
              obj) in which an AClass 
              object, as well as an object of an AClass 
              subclass type, passes as an AClass 
              type argument. The method will invoke aMethod() 
              regardless of the type of object and if it is a BClass 
              object, it will also invoke bMethod(). 
              It can use the instanceof 
              operator to determine the type.   
              
                 
                  | public 
                    void 
                    miscMethod (AClass obj) { obj.aMethod ();
 if (obj instanceof 
                    BClass) ((BClass)obj).bMethod ();
 }
 |  To invoke the BMethod(), 
                the operation (BClass)obj 
                tells the compiler to treat the AClass 
                object referenced by obj 
                as if it is a BClass 
                object. Without the cast, the compiler will give an error message 
                indicating that bMethod() cannot be found in the AClass 
                definition.  Cast Rules The casting rules can be confusing, but in most cases 
              common sense applies. There are compile-time rules and runtime 
              rules. The compile-time rules are there to catch attempted casts 
              in cases that are simply not possible.  For instance, suppose we have classes A and B that 
              are completely unrelated - i.e., neither inherits from the other 
              and neither implements the same interface as the other, if any. 
              It is nonsensical to attempt to cast a B object to an A object, 
              and the compiler does not permit it even with an explicit cast. 
              Instead, the compiler issues an "inconvertible types" error message. 
             Casts that are permitted at compile-time include casting 
              any object to its own class or to one of its sub or superclass types 
              or interfaces. Almost anything can be cast to almost any interface, 
              and an interface can be cast to almost any class type. There are 
              some obscure cases (see the Java Language Specification for the 
              details), but these common sense rules cover most situations.  The compile-time rules cannot catch every invalid 
              cast attempt. If the compile-time rules permit a cast, then additional, 
              more stringent rules apply at runtime. These runtime rules basically 
              require that the object being cast is compatible with the new type 
              it is being cast to. Else, a ClassCastException is thrown at runtime. 
             References & Web Resources 
               The 
                Object class - the base class for all Java classes. Can always 
                treat a Java object as an Object 
                type. Latest update: Oct. 20, 2004 |