views:

612

answers:

3
import java.util.Collection;


public class Test
{
    public static void main(String[] args)
    {
        Collection c = null;
        Test s = null;

        s = (Test) c;
    }
}

In the code sample above, I am casting a collection object to a Test object. (ignoring the null pointer). Test has no relationship to Collection whatsoever, yet this program will pass all compile-time checks.

I'm wondering why this is. My assumption is that interfaces are ignored because they are too complicated. They have no common super-type and each class can implement several interfaces, so the class/interface hierarchy would be too complicated to search efficiently?

Other than that reason I am stumped though. Does anyone know?!

+6  A: 

"Non-final" is a keyword here. You may have another class

public class Test2 extends Test implements Collection

whose instance will end up being assigned to s making a cast perfectly legal.

ChssPly76
Ah, I see.If no subclass of Test implemented Collection, I would still have expected the downcast to fail (similar to how casts fail in a strictly class-only hierarchy if the type isn't found). Is that because it's not worth the effort?
Jack Griffith
The compiler cannot make any assumptions about the class subclasses. Unless the class is marked as `final`, you can subclass it using its classfile.
notnoop
In other words, just because there is no subclass at compile-time, it doesn't mean that there cannot be one at runtime.
notnoop
No, it's because there's no way to know that no subclass of Test implemented Collection unless Test is final. Your example is very simple, but in real life I can have an extending class loaded over network / injected via AOP proxy / what have you
ChssPly76
Thank you for the explanations. :)
Jack Griffith
+3  A: 

Because a subclass of Test can potentially be a subtype of Collection as well! The language specification is designed to be a bit flexible to permit casts that can be verified at run-time.

notnoop
+1  A: 

There's no harm casting this to type Test until it's used as a Test (ie. a mehod on Test is called on s). At this point, there would be an exception thrown.

Zack
Not quite true. Java tries to ensure type-safety at compile-time as much as possible. It prevents impossible casts to final classes for example.
notnoop