A iterator with a generic method next()?

Maurizio Cimadamore Maurizio.Cimadamore at Sun.COM
Thu Nov 12 13:38:06 PST 2009


Paulo Levi wrote:
> Actually i think i found a bug in the compiler with these shenanigans
> (one that makes my idea almost useless). One would think
> that this class would call the method, catch the exception inside it
> and then return the (correct) instance.
> Apparently the compiler only introduces the casts at the outer part of
> the method. Not inside, so the class cast exception
> is never caught.
>   

The issue described in your email is known as 'heap pollution' - it is a 
very well-known scenario that is decribed in JLS 3rd edition, section 
4.12.2.1 [1]. I think you are complaining about the 'missing' 
ClassCastException here:

return (T) raw;


Well, the compiler uses a technique called 'erasure' which removes 
generics during compilation. This means that your code is actually 
translated to something like:

return (Object)raw;

As you can see, there's no ClassCastException generated here, as casting 
from raw to Object is perfectly legal.
On the other hand since the compiler knows that it's statically unsafe 
to cast an Object into a T, it generates a so-called unchecked warning. 
This warning is there to remind you that your code doesn't comply with 
static typing rules enforced by the compiler and can be subject to weird 
failures, such as the ClassCastException (at a later point) you are 
complaining about.

Where does the CCE comes from? At the call site:

String s = failingCatchingClassCastException(new Callable() { ... }

is translated 

String s = (String)failingCatchingClassCastException(new Callable() {


Note that the cast here is necessary, as the signature of the method has 
been erased (meaning that every occurrence of T has been replaced by 
Object).

Bottom line: never ignore unchecked warnings unless you are 100% sure 
about what you are doing.

[1] 
http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.12.2.1
> I'm disappointed. Feet of clay and all that for the compiler.
>
> public class Main{
>
>     public static void main(String[] args) {
>         String s = failingCatchingClassCastException(new Callable() {
>
>             public Object call() throws Exception {
>                 return "Hi BUG";
>             }
>         });
>     }
>
>     public static <T> T failingCatchingClassCastException(Callable t) {
>         try {
>             Object raw = new Object();
>             return (T) raw;
>         } catch (ClassCastException ex) {
>             System.out.println("WTF!!!");
>         }
>         try {
>             return (T) t.call();
>         } catch (Exception ex) {
>             return null;
>         }
>     }
> }
>
>   




More information about the coin-dev mailing list