Explanation of Classcastexception in Java

Explanation of ClassCastException in Java

Straight from the API Specifications for the ClassCastException:

Thrown to indicate that the code has
attempted to cast an object to a
subclass of which it is not an
instance.

So, for example, when one tries to cast an Integer to a String, String is not an subclass of Integer, so a ClassCastException will be thrown.

Object i = Integer.valueOf(42);
String s = (String)i; // ClassCastException thrown here.

java.lang.ClassCastException

According to the documentation:

Thrown to indicate that the code has attempted to cast an Object to a subclass
of which it is not an instance. For example, the following code generates a ClassCastException:

Object x = new Integer(0);
System.out.println((String)x);

What else can throw a ClassCastException in java?

One reason could be that the part of the code inserting the object uses a different classloader than the code retrieving it.

An instance of a class can not be cast to the same class loaded by a different classloader.

Response to the edit:

What would you do if this happened in production?

This generally happens when the reading and inserting modules each include the same jar containing C1.

Since most containers try the parent classloader first, and then the local classloader (the Parent first strategy), the common solution to the problem is to instead load the class in the closest common parent to the inserting and reading modules.

If you move the module containing the C1 class to the parent module, you force both submodules to get the class from the parent, removing any classloader differences.

Java Socket ClassCast Exception

Please, see the row 20 of the ServidorTCP class.
You can't cast the value that is returned by "getObjectFromByte" method to an "Archivio", because it is not of a compatible type. In particular, it is an Integer.
It happens because the read method of the ObjectInputStream returns an int (See Javadoc).

Why a ClassCastException but not a compilation error?

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.

Java inheritance downcast ClassCastException

All B's are A's, by inheritance. But not all A's are B's. This particular instance isn't, hence the runtime exception.

Meaning of java.lang.ClassCastException: someClass incompatible with someClass

Philippe Riand explaned this by email:

This class cast happens because the same class had been loaded twice by 2 different class loaders. Thus, from a Java standpoint, they are different and the cast fails.

Now, each XPages application is having its own classloader. But this class loader is discarded each time a design change happens to the application, through Domino Designer for example. This is required as a change to an XPages generates a new Java class that should then be loaded instead of the previous one. When this happens, the classloader is discarded and a new is created. Then all the application related classes are reloaded, as they are needed, even though they didn't change.This is a common behavior implemented by J2EE servers.
That said, if your code is caching an object in a scope that is not discarded when a design change occurs, then this is likely to happen. For example, the applicationScope & sessionScope are currently not discarded when a design change happens, which might lead to this problem. This was a design choice as discarding the scopes sometimes provides a bad developer experience, but with this drawback.

Finally, saving faces-config.xml works as a workaround. When this file is saved, then the entire module is discarded from memory, including the scopes, This explains why it works. Making a change to your custom Java class should reload the module and remove the issue.

So it seems putting beans (even indirectly) into sessionScope or applicationScope is the cause.



Related Topics



Leave a reply



Submit