Search code examples
javagenericstype-safety

Why is upcasting a Class considered an unsafe operation?


Why does the Java compiler trigger an "unchecked cast" warning when casting Class<? extends Object> to Class<Object>? How could this cast possibly fail?


Solution

  • Such a cast is simply not safe in general, and the fact that it is safe for the Class class can not be detected. Imagine a class like this:

    // Hypothetical!
    class MyClass<T> extends Class<T> {
        public T someInstance;
    }
    

    Now, if the cast in question was allowed, you could do something like

    MyClass<Integer> myClassWithInteger = new MyClass<Integer>();
    myClassWithInteger.someInstance = someInteger;
    
    // This is valid
    MyClass<? extends Object> myClassWithWildcard = myClassWithInteger; 
    
    // This is NOT valid, but let's assume it was:
    MyClass<Object> myClassWithObject = myClassWithWildcard; 
    
    // This would be valid, because 'someInstance' was of type 'Object' here
    myClassWithObject.someInstance = "someString";
    
    // This is valid. But through the unchecked cast, we silently
    // sneaked in an STRING as this instance. So this would fail:
    Integer i = myClassWithInteger.someInstance;
    

    You asked in the comment:

    Are you saying that the language authors wanted to avoid special treatment for safe classes like Class so they forbid this across the board?

    Yes. The crucial point is that the question whether such a cast is safe or not depends on the semantics of the class. The safety can not be detected syntactically.