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
|