[e-lang] Type safety of Java generics

Constantine Plotnikov constantine.plotnikov at gmail.com
Tue May 29 09:36:39 EDT 2007


The reflection behavior is not unlike one of the complier. The
compiler error could be very easily stripped down as well. So
reflection have the same safety guarantees as static type checking
(broken ones).

import java.util.ArrayList;

public class UnsafeGenerics2 {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
       // After type erasure, this is really an ArrayList of Object.
       ArrayList<String> a = new ArrayList<String>();
       // two lines below could happen when object is got from
       // HTTP session for example or used in legacy code.
       ArrayList<Integer> b = (ArrayList<Integer>)(Object)a;
       b.add(42);
       // This doesn't provoke a warning, but fails with a
       // ClassCastException at run-time.
       String s = a.get(0); // line 32
   }
}

So situation normal, all is broken as expected.

Constantine

On 5/29/07, David Hopwood <david.hopwood at industrial-designers.co.uk> wrote:
> /*
> 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>
>
> _______________________________________________
> e-lang mailing list
> e-lang at mail.eros-os.org
> http://www.eros-os.org/mailman/listinfo/e-lang
>


More information about the e-lang mailing list