Why a ClassCastException but not a compilation error?
Asked Answered
L

3

6

Why don't I get a compilation error in the code below? I get a ClassCastException which is a little confusing. Is it because they are related?

class Ink {}

Interface Printable {}
class ColorInk extends Ink implements Printable {}

class BlackInk extends Ink {}


class TwistInTaleCasting {
   public static void main(String args[]) {
       Printable printable = null;
       BlackInk blackInk = new BlackInk();
       printable = (Printable)blackInk;
   }
}
Lure answered 15/8, 2014 at 12:37 Comment(5)
Compiler does not check explicit casts, but the runtime does. Thus, when running you get the classcastexception.Logo
This is very basic stuff but IMO doesn't deserve a downvote - the question is clearly articulated, it has enough information to describe the problem and the user posting it needs an answer.Haemo
@Pphoenix: The compiler does check explicit casts - it checks that the cast is sensible. (See my answer for an example.)Mountbatten
@JonSkeet Hmm, since neither BlackInk nor Ink is Printable, how (or rather why) does the compiler approve the cast?Logo
@Pphoenix: Again, read my answer - the value of blackInk could be a reference to an instance of a class extending BlackInk and implementing Printable. It compiles for the same reason that Object o = new Object(); String x = (String) o; compiles...Mountbatten
M
12

Why don't I get a compilation error in the code below?

Because the compiler only cares about the static type of the expression you're trying to cast.

Look at these two lines:

BlackInk blackInk = new BlackInk();
printable = (Printable)blackInk;

You know that in the second line, the value blackInk only refers to an object of type BlackInk due to the first line, but the compiler doesn't. For all the compiler knows (when compiling the second line) it could actually have been:

BlackInk blackInk = new PrintableBlackInk();
printable = (Printable)blackInk;

... where PrintableBlackInk is a class extending BlackInk and implementing Printable. Therefore it's valid (at compile-time) to cast from an expression of type BlackInk to Printable. If you make BlackInk a final class, then the compiler knows that there's no way that it will work (unless the value is null) and will fail at compile-time, like this:

error: inconvertible types
          printable = (Printable)blackInk;
                                 ^
required: Printable
found:    BlackInk

The details for this are in JLS 5.5.1.

Otherwise, we have to wait until execution time to see the failure, because the cast is valid at compile-time.

Mountbatten answered 15/8, 2014 at 12:44 Comment(0)
E
3

ClassCastException is runtime exception which is why you get to compile your code but get the ClassCastException at runtime. You can check the javadocs as well - ClassCastException extends the RuntimeException: http://docs.oracle.com/javase/7/docs/api/java/lang/ClassCastException.html

The reason why you get the ClassCastException is obviously because you are trying to cast an instance of BlackInk to Printable (when you cast an object to a subclass of which it is not an instance, you will get the ClassCastException at runtime). In short, when you are casting, you're using type conversion and it needs to be a valid operation else you will get a ClassCastExecption at runtime.

Endotoxin answered 15/8, 2014 at 12:40 Comment(0)
S
0

The setup will compile properly. However at runtime, since TwistInTaleCasting and Printable have no relation a class cast exception is thrown. Since ClassCastException is ** notchecked exception** it's alright to not handle any such case in your code.

Semiramis answered 15/8, 2014 at 12:43 Comment(1)
OP asked why, You haven't answered.Butanol

© 2022 - 2024 — McMap. All rights reserved.