3

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.

Paul Bellora
  • 51,514
  • 17
  • 127
  • 176
Marcus Junius Brutus
  • 23,022
  • 30
  • 155
  • 282
  • You are making an assumption that the object returned by the external library method `Object newHolder()` will be `Holder` and hence, despite the compiler-warning, explicitly casting the result. Which means you are telling the compiler - *I know better.* But your assumption is wrong. When making such a decision, you should not make assumption, but be hundred percent sure. – Bhesh Gurung Jun 03 '13 at 14:00
  • related: http://stackoverflow.com/a/12209857/697449 – Paul Bellora Jun 03 '13 at 14:07

2 Answers2

2

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...

Community
  • 1
  • 1
BobTheBuilder
  • 17,650
  • 5
  • 35
  • 58
2

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.

Michael Berry
  • 61,291
  • 17
  • 134
  • 188
  • Not just any cast, but an *unchecked* cast, which means a wrong generic type will *not* fail fast with a `ClassCastException`. – Paul Bellora Jun 03 '13 at 14:04