beoliver
beoliver

Reputation: 5759

Narrowing Reference Conversion

taken from http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

5.1.6. Narrowing Reference Conversion Six kinds of conversions are called the narrowing reference conversions: From any reference type S to any reference type T, provided that S is a proper supertype of T ...

public class S {}

public class T extends S {}

As the following throws a java.lang.ClassCastException

S s = new S();
T t = (T)s;

does the 'conversion' simply refer to the following that compiles does not throw a run-time exception.

S s = null;
T t = (T)s;

What are the reasons for performing this conversion?

Upvotes: 4

Views: 869

Answers (2)

dingalapadum
dingalapadum

Reputation: 2177

Although implicit in Sotirios Delimanolis's example (// something), I wanted to add to this and make it explicit that if you have:

public class S {}
public class T extends S {}

then the narrowing conversion in the JLS not only refers to your example with null but rather to:

S s = new T();
T t = (T) s; // compiles and won't give a ClassCastException

while as you mentioned

S s = new S();
T t = (T) s;

will compile but will throw a ClassCastException

Upvotes: 2

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279930

Further in the document you quoted, it states

Such conversions require a test at run time to find out whether the actual reference value is a legitimate value of the new type. If not, then a ClassCastException is thrown.

The conversion applies to your first example as well. A value of type S is not a legitimate value of type T. The value null is a legitimate value of type T.

The null reference can always be assigned or cast to any reference type (§5.2, §5.3, §5.5).

The compiler trusts that you know what you are doing. The JVM does not.

A narrowing reference conversion is more commonly known as a downcast. It's typically used in situations where you have references of some supertype but would like to do something more specific with them depending on their actual type.

Object superTypeReference = // something;
if (superTypeReference instanceof List) {
    List<?> subtypeReference = (List<?>) superTypeReference;
    subtypeReference.clear();
}

Upvotes: 3

Related Questions