[e-lang] Type safety of Java generics
David Hopwood
david.hopwood at industrial-designers.co.uk
Mon May 28 14:13:49 EDT 2007
/*
In the Friday meeting, one of the things we discussed was the type safety
of Java 1.5 generics. I said that I would come up with an example in which:
- the compiler does not output any warnings;
- there are reflective operations, but none of those operations fail
at run-time;
- a non-reflective operation fails with a type error at run-time.
Here is the example.
*/
import java.util.ArrayList;
import java.lang.reflect.*;
public class UnsafeGenerics {
public static void main(String[] args) {
// After type erasure, this is really an ArrayList of Object.
ArrayList<String> a = new ArrayList<String>();
// The reflection API can put a non-String into the ArrayList.
try {
Method m = ArrayList.class.getMethod("add", Object.class);
m.invoke(a, new Integer(42));
} catch (Exception e) {
System.err.println("reflective operation failed");
throw new RuntimeException(e);
}
// This doesn't provoke a warning, but fails with a
// ClassCastException at run-time.
String s = a.get(0); // line 32
}
}
>javac UnsafeGenerics.java
>java UnsafeGenerics
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer
cannot be cast to java.lang.String
at UnsafeGenerics.main(UnsafeGenerics.java:32)
>java -version
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)
>javac -version
javac 1.6.0_01
What is objectionable about this is that:
- the reflection API silently allowed an object to get into a state that
violates its declared type;
- the compiler inserted an *implicit* cast that failed, without any warning.
Of course, in a real program the cast failure could be arbitrarily far
away (in time and code location) from the unsafe reflective operation.
--
David Hopwood <david.hopwood at industrial-designers.co.uk>
More information about the e-lang
mailing list