why not compile error on "incompatible interface cast"?

Discussion in 'Java' started by gg9h0st, Jul 26, 2008.

  1. gg9h0st

    gg9h0st Guest

    simeple code here

    -----------------------------------------------------------
    class IncompInterfaceTest {
    void doTest() {
    ClassB b = new ClassB();
    InterfaceA a = (InterfaceA)b;
    }
    }

    interface InterfaceA{}
    class ClassB{}
    -----------------------------------------------------------

    javac issues "ClassCastException" on runtime rather than compile
    error.

    as i know incompatible type casting may be caught at runtime and
    compiler shows the error.

    but why compiler doesn't do it's job for interfaces? it's just so
    clear to be compile error to me.
    gg9h0st, Jul 26, 2008
    #1
    1. Advertising

  2. gg9h0st wrote:
    > simeple code here
    >
    > -----------------------------------------------------------
    > class IncompInterfaceTest {
    > void doTest() {
    > ClassB b = new ClassB();
    > InterfaceA a = (InterfaceA)b;
    > }
    > }
    >
    > interface InterfaceA{}
    > class ClassB{}
    > -----------------------------------------------------------
    >
    > javac issues "ClassCastException" on runtime rather than compile
    > error.
    >
    > as i know incompatible type casting may be caught at runtime and
    > compiler shows the error.
    >
    > but why compiler doesn't do it's job for interfaces? it's just so
    > clear to be compile error to me.


    In theory, the compiler could apply flow analysis in your test case to
    conclude that b references the new ClassB() result at the point of the
    cast.

    Without flow analysis, the compiler only knows that you are casting a
    ClassB reference to InterfaceA. Its value might be a pointer to a ClassC
    object, where extends ClassB and implements InterfaceA

    In general, given a non-final class and an interface, the compiler has
    to allow for the possibility that the class has a subclass that
    implements the interface.

    Patricia
    Patricia Shanahan, Jul 26, 2008
    #2
    1. Advertising

  3. gg9h0st

    gg9h0st Guest

    > In theory, the compiler could apply flow analysis in your test case to
    > conclude that b references the new ClassB() result at the point of the
    > cast.
    >
    > Without flow analysis, the compiler only knows that you are casting a
    > ClassB reference to InterfaceA. Its value might be a pointer to a ClassC
    > object, where extends ClassB and implements InterfaceA
    >
    > In general, given a non-final class and an interface, the compiler has
    > to allow for the possibility that the class has a subclass that
    > implements the interface.
    >
    > Patricia


    I think I saw you a year ago here too lol

    by the way :S I modified this reply so many time while I'm
    understanding what you told. still unclear ^^;

    so it is about implementing interface is not like extending a class.
    right?

    I may need abit time more to think right now.

    thanks patricia :)
    gg9h0st, Jul 26, 2008
    #3
  4. gg9h0st

    gg9h0st Guest

    > In theory, the compiler could apply flow analysis in your test case to
    > conclude that b references the new ClassB() result at the point of the
    > cast.
    >
    > Without flow analysis, the compiler only knows that you are casting a
    > ClassB reference to InterfaceA. Its value might be a pointer to a ClassC
    > object, where extends ClassB and implements InterfaceA
    >
    > In general, given a non-final class and an interface, the compiler has
    > to allow for the possibility that the class has a subclass that
    > implements the interface.
    >
    > Patricia


    Another Qeustion along this.

    Doesn't "cast operator" know it's actuall object?

    em... cast operator test it's operand as a refernce variable, not far
    to the object in compile stage.

    and extending a class should be clear to test whle implementing a
    interface is not.

    is that right?
    gg9h0st, Jul 26, 2008
    #4
  5. gg9h0st wrote:
    > Doesn't "cast operator" know it's actuall object?
    >
    > em... cast operator test it's operand as a refernce variable, not far
    > to the object in compile stage.
    >
    > and extending a class should be clear to test whle implementing a
    > interface is not.
    >
    > is that right?
    >


    I don't totally understand what you're trying to say, but I'll take a
    gander.

    In principle, there is sufficient information at compile time to be
    determine that the cast will fail. Such analysis, though, is impractical
    or even impossible in all cases. I am not certain, but I believe that if
    ClassB were final, the cast would be a compiler error.

    A compiler sees the statement as "cast reference of type T1 to a
    reference of type T2"; it would need additional information to be stored
    to be able to prove that the object cannot, in fact, be type T2. Tools
    which perform such analysis do exist, and fall under the heading of
    "static analysis," which retains more information about statements in
    order to detect which ones could be or are problematic. FindBugs is a
    classic example of such a tool for Java.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Jul 26, 2008
    #5
  6. gg9h0st

    gg9h0st Guest

    On 7¿ù27ÀÏ, ¿ÀÀü9½Ã03ºÐ, Lew <com.lewscanon@lew> wrote:
    > gg9h0st wrote:
    > >> class IncompInterfaceTest {
    > >> void doTest() {
    > >> ClassB b = new ClassB();
    > >> InterfaceA a = (InterfaceA)b;
    > >> }
    > >> }

    >
    > >> interface InterfaceA{}
    > >> class ClassB{}
    > >> javac issues "ClassCastException" on runtime rather than compile
    > >> error.

    >
    > >> as i [sic] know incompatible type casting may be caught at runtime and
    > >> compiler shows the error.

    > Patricia Shanahan wrote:
    > > In general, given a non-final class and an interface, the compiler has
    > > to allow for the possibility that the class has a subclass that
    > > implements the interface.

    >
    > From the JLS section 5.5:
    >
    > > The detailed rules for compile-time legality of a casting conversion of a
    > > value of compile-time reference type S to a compile-time reference type T
    > > are as follows:

    > ...
    > > If S is a class type:

    > ...
    > > * If T is an interface type:
    > > o If S is not a final class (¡×8.1.1), then, if there exists a supertype X of
    > > T, and a supertype Y of S, such that both X and Y are provably distinct
    > > parameterized types, and that the erasures of X and Y are the same, a
    > > compile-time error occurs. Otherwise, the cast is always legal at compile time
    > > (because even if S does not implement T, a subclass of S might).

    >
    > Take S as ClassB and T as InterfaceA.
    >
    > --
    > Lew


    ooooooooowwwww~~ I still don't get it :S
    that "a subclass of S might" part.

    so compiler doesn't know what variable 'b' hold? that is oviously
    ClassB.

    if where ClassC extends ClassB implements InterfaceA

    b = new ClassC();
    means b hold ClassC object in a ClassB variable.
    It CAN BE ClassB, It IS NOT ClassB.
    gg9h0st, Jul 27, 2008
    #6
  7. gg9h0st

    gg9h0st Guest

    On 7¿ù27ÀÏ, ¿ÀÈÄ12½Ã17ºÐ, "Peter Duniho" <>
    wrote:
    > On Sat, 26 Jul 2008 20:07:55 -0700, gg9h0st <> wrote:
    > > ooooooooowwwww~~ I still don't get it :S
    > > that "a subclass of S might" part.

    >
    > > so compiler doesn't know what variable 'b' hold? that is oviously
    > > ClassB.

    >
    > There are things that are obvious to a human reader that are not obvious
    > to the compiler.
    >
    > The case you're talking about is a degenerate case, but there are similar
    > situations in which analysis of the execution of the code _could_ prove
    > that the cast would succeed or fail, but such analysis would be _much_
    > more complicated than simply looking at the initialization of the variable.
    >
    > For a variety of reasons, but I think mainly just to keep things
    > consistent (consistent, predictable compiler behavior is always a nice
    > thing :) ), the compiler is simply going to assume that all such casts are
    > valid. It's not feasible to verify them in all cases, and so rather than
    > provide inconsistent behavior, the compiler doesn't bother to verify them
    > in any case. It's up to you, the author of the code, to not perform casts
    > that will fail.
    >
    > Basically: pretend you're a compiler. Look at _just_ the statement being
    > compiled. Based solely on that statement and _statically_ known things
    > (e.g. the types of the identifiers in the statement), can you prove that
    > the cast is valid or invalid?
    >
    > The answer to that question is "no". And that's exactly why the compiler
    > can't prove it either.
    >
    > Pete


    yea T_T

    I spend so much time to digging it.

    what you explained me makes me somehow easy. need to sleep lol

    I just found that doesn't make an error while casting class on an
    incompatible hierarchy makes an error.
    and wanted to know.
    ( ClassB extends ClassA, ClassD extends ClassC,
    casting ClassD to ClassB issues an error.
    while ClassB implements InterfaceA, ClassD implements InterfaceD,
    casting ClassD to ClassB doesn't.)

    I better leave it to "compiler does like this" and move to the other
    studies as a newbie.

    thanks :)
    gg9h0st, Jul 27, 2008
    #7
  8. gg9h0st

    Daniel Pitts Guest

    gg9h0st wrote:
    > On 7¿ù27ÀÏ, ¿ÀÈÄ12½Ã17ºÐ, "Peter Duniho" <>
    > wrote:
    >> On Sat, 26 Jul 2008 20:07:55 -0700, gg9h0st <> wrote:
    >>> ooooooooowwwww~~ I still don't get it :S
    >>> that "a subclass of S might" part.
    >>> so compiler doesn't know what variable 'b' hold? that is oviously
    >>> ClassB.

    >> There are things that are obvious to a human reader that are not obvious
    >> to the compiler.
    >>
    >> The case you're talking about is a degenerate case, but there are similar
    >> situations in which analysis of the execution of the code _could_ prove
    >> that the cast would succeed or fail, but such analysis would be _much_
    >> more complicated than simply looking at the initialization of the variable.
    >>
    >> For a variety of reasons, but I think mainly just to keep things
    >> consistent (consistent, predictable compiler behavior is always a nice
    >> thing :) ), the compiler is simply going to assume that all such casts are
    >> valid. It's not feasible to verify them in all cases, and so rather than
    >> provide inconsistent behavior, the compiler doesn't bother to verify them
    >> in any case. It's up to you, the author of the code, to not perform casts
    >> that will fail.
    >>
    >> Basically: pretend you're a compiler. Look at _just_ the statement being
    >> compiled. Based solely on that statement and _statically_ known things
    >> (e.g. the types of the identifiers in the statement), can you prove that
    >> the cast is valid or invalid?
    >>
    >> The answer to that question is "no". And that's exactly why the compiler
    >> can't prove it either.
    >>
    >> Pete

    >
    > yea T_T
    >
    > I spend so much time to digging it.
    >
    > what you explained me makes me somehow easy. need to sleep lol
    >
    > I just found that doesn't make an error while casting class on an
    > incompatible hierarchy makes an error.
    > and wanted to know.
    > ( ClassB extends ClassA, ClassD extends ClassC,
    > casting ClassD to ClassB issues an error.
    > while ClassB implements InterfaceA, ClassD implements InterfaceD,
    > casting ClassD to ClassB doesn't.)
    >
    > I better leave it to "compiler does like this" and move to the other
    > studies as a newbie.
    >
    > thanks :)

    The real reason is that the compiler can easily prove that two classes
    are not castable to each-other, but interfaces are trickier, because any
    Object might be implementing an interface.

    In your example, ClassD to ClassC actually would cause compiler error,
    where ClassD to InterfaceA would not. The compiler can not disprove the
    existance of ClassE extends ClassD implement InterfaceA. ClassE might
    not have been written yet, but it might be available at run-time, and
    the cast need not know about it at compile time to succeed.

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, Jul 27, 2008
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    877
    Mark Rae
    Dec 21, 2006
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,805
    Smokey Grindel
    Dec 2, 2006
  3. Nagaraj
    Replies:
    1
    Views:
    853
    Lionel B
    Mar 1, 2007
  4. Paul Melis

    Why oh why does this NOT give a compile error?

    Paul Melis, Nov 5, 2007, in forum: C Programming
    Replies:
    13
    Views:
    511
    cr88192
    Nov 7, 2007
  5. fAnSKyer
    Replies:
    2
    Views:
    529
    Alf P. Steinbach
    Jun 7, 2009
Loading...

Share This Page