Cast reference of known type to an interface outside of type's hierarchy

后端 未结 6 1293
无人及你
无人及你 2021-01-20 11:44

Say you have a clean class like this:

public class A {
    // Stuff
}

And a interface like this:

public interface G {
    /         


        
相关标签:
6条回答
  • 2021-01-20 11:53

    Casting means you know better than the compiler what's valid. You are telling the compiler to shut up and follow your lead. The compiler can tell in a few cases that a cast is invalid, but it is easy to fool.

    Most casts tend to be from Object to something else, such as in getting an object out of a non-genericized collection or when getting a remote object using PortableRemoteObject.narrow. These casts always compile because whatever you cast to (as long as it's an Object, and not a primitive) is always a valid subclass of Object.

    There are some rules for casting in the Java language specification in the section Reference Type casting (5.5.1). If the compiler can figure out there is no relationship between the classes (the compiler can tell the classes are different and neither is a subclass of the other) then it will reject the cast.

    The added example is interesting, it fails because the compiler has enough information to tell that the cast is invalid. If you change the code to:

        A a = new A();
        G g = (G)a;
        Object o = a;
        C c = (C)o;
    

    then it compiles fine again (even though it is just as erroneous).

    0 讨论(0)
  • 2021-01-20 11:54

    Sure, but this is also valid:

    public class A {}
    public class B {}
    
    A a = new A();
    ((B) a);
    

    You can cast almost anything to anything, casting is for when you know what type you want.

    (However when you use some casts, such as the example above, you'll get a ClassCastException at runtime when Java realizes that it won't cast right.)

    0 讨论(0)
  • 2021-01-20 11:58

    Casting correctness can only be checked at runtime. So in your example, even though it might be obvious to you, for the program it won't know it's incorrect until it's actually running and attempts to cast the variable a as the interface G. At this point it will throw a ClassCastException.

    0 讨论(0)
  • 2021-01-20 12:09

    This is allowed at compile time, because the Java compiler lets you do this; it assumes you know what you're doing.

    However, the JVM figures it out and throws a ClassCastException at runtime.

    0 讨论(0)
  • 2021-01-20 12:14

    The issue here is that because G is an interface, it is possible that there is a subclass of A that implements G. Therefore it's at least possible that at runtime the type of the object stored in a implements G.

    "But I just assigned a to contain type A! Stupid compiler!" It's important to remember that when assessing the potential success of a cast, the compiler looks only at the compile-time type of the variable. As such, the compiler doesn't try to figure out what will actually be in the variable, it just looks at the type of the variable itself.

    Note that if you declare A to be final, then this becomes a compile-time error, since now the compiler knows there are no subclasses of A, and A itself doesn't implement G, and so the cast can never succeed at runtime.

    Finally, the same logic applies to casting C to A: C doesn't derive from A, and the compiler knows that no subclass of C derives from A (since they all derive from C at some point!) and so there's no possibility that the cast could succeed at runtime.

    0 讨论(0)
  • 2021-01-20 12:15

    The compiler doesn't necessarily know whether or not a implements G or not.

    Casting pretty much tells the compiler to take this variable, and treat it like a different type.

    If you try to do an operation on the cast variable as though it implemented G(when it doesn't) you'll get a runtime error

    0 讨论(0)
提交回复
热议问题