Domanda

This is a narrow-down example of a case I came across.

Take a look at the code below:

class Holder<T> {
    private T t;
    public Holder(T t) {
        this.t = t;
    }
    public T getValue() {
        return t;
    }
}

public class FooMain {

    private static Object newHolder() {
        return new Holder<Integer>(3);
    }

    public static void main(String args[]) {
        Holder<String> hs = (Holder<String>) newHolder(); // line-18
        String s = hs.getValue();                         // line-19
    }
}

What spooked me is that the inevitable ClassCastException gets thrown on line-19 and not on line-18 !

Therefore, having an object in your code that's of type Holder<String> is not enough to guarantee that getValue will return a String. You also have to examine how this object was constructed!

I understand that Type Erasure plays a role here but I am not sure how wide the implications of the above are. In my particular case the newHolder-corresponding method is defined in an external library and returns java.lang.Object so I have to do these casts.

È stato utile?

Soluzione

You will get a warning when this is compiled, saying that you're performing a cast that means the compiler can't guarantee type safety. When you make these casts and get these warnings, you're essentially on your own. Since generics are implemented using erasure in Java the generic type information disappears at runtime - it's purely a compile time construct, and thus if you circumvent this the runtime may not know until later that you've performed an invalid cast.

Altri suggerimenti

Generics are compile time tool to check for type safety. In runtime there's no validation, as of type erasure. That's why you get an error getting a String from an Integer.

BTW, you should get a warning when casting. Ignoring the warning may have consequences...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top