juliovr
juliovr

Reputation: 48

ClassCastException but still compiles

A co-worker showed me this code and I know it won't work (In fact, at runtime throws ClassCastException when you run it).

I don't know why it compiles, because it cast from java.io.FileInputStream to org.springframework.core.io.InputStreamSource; none of them implements the same interfaces or extends the same classes in hierarchies.

try (InputStream fileInputStream = new FileInputStream("somefile")) {

    InputStreamSource file = (InputStreamSource) fileInputStream;

    // some code

} catch (IOException e) {
    // some code
}

Link of respective documentation classes: FileInputStream , InputStreamSource

Upvotes: 2

Views: 99

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074188

I don't know why it compiles...

Because it's an explicit cast between a non-final reference type and an interface. An explicit cast between reference types says to the compiler: "Look, I (the programmer) know that this cast will be valid at runtime. Trust me." So it does. Later at runtime, of course, since the programmer was wrong, it fails.

The compiler doesn't blindly trust the programmer, though. Details in §JLS5.5, but if the compiler can prove that it's impossible for the cast to be valid, it'll still reject the cast. It can't do that in your case, though, because InputStreamSource is an interface, and FileInputStream is a non-final class. So the FileInputStream could well be referring to some subclass object that implements InputStreamSource. (Of course, we can tell from looking at it that it isn't, since it was just set to the result of new FileInputStream. But the compiler doesn't look quite that hard, it only cares about the types involved in the casting.)

Upvotes: 4

Momo
Momo

Reputation: 76

Because it's an explicit cast. The compiler trusts you that the cast will be valide at runtime, so if it's not the case it fails.

Upvotes: 2

Related Questions