[java] Java Class.cast() vs. cast operator

Having being taught during my C++ days about evils of the C-style cast operator I was pleased at first to find that in Java 5 java.lang.Class had acquired a cast method.

I thought that finally we have an OO way of dealing with casting.

Turns out Class.cast is not the same as static_cast in C++. It is more like reinterpret_cast. It will not generate a compilation error where it is expected and instead will defer to runtime. Here is a simple test case to demonstrate different behaviors.

package test;

import static org.junit.Assert.assertTrue;

import org.junit.Test;


public class TestCast
{
    static final class Foo
    {
    }

    static class Bar
    {
    }

    static final class BarSubclass
        extends Bar
    {
    }

    @Test
    public void test ( )
    {
        final Foo foo = new Foo( );
        final Bar bar = new Bar( );
        final BarSubclass bar_subclass = new BarSubclass( );

        {
            final Bar bar_ref = bar;
        }

        {
            // Compilation error
            final Bar bar_ref = foo;
        }
        {
            // Compilation error
            final Bar bar_ref = (Bar) foo;
        }

        try
        {
            // !!! Compiles fine, runtime exception
            Bar.class.cast( foo );
        }
        catch ( final ClassCastException ex )
        {
            assertTrue( true );
        }

        {
            final Bar bar_ref = bar_subclass;
        }

        try
        {
            // Compiles fine, runtime exception, equivalent of C++ dynamic_cast
            final BarSubclass bar_subclass_ref = (BarSubclass) bar;
        }
        catch ( final ClassCastException ex )
        {
            assertTrue( true );
        }
    }
}

So, these are my questions.

  1. Should Class.cast() be banished to Generics land? There it has quite a few legitimate uses.
  2. Should compilers generate compile errors when Class.cast() is used and illegal conditions can be determined at compile time?
  3. Should Java provide a cast operator as a language construct similar to C++?

This question is related to java generics casting compiler-warnings

The answer is


First, you are strongly discouraged to do almost any cast, so you should limit it as much as possible! You lose the benefits of Java's compile-time strongly-typed features.

In any case, Class.cast() should be used mainly when you retrieve the Class token via reflection. It's more idiomatic to write

MyObject myObject = (MyObject) object

rather than

MyObject myObject = MyObject.class.cast(object)

EDIT: Errors at compile time

Over all, Java performs cast checks at run time only. However, the compiler can issue an error if it can prove that such casts can never succeed (e.g. cast a class to another class that's not a supertype and cast a final class type to class/interface that's not in its type hierarchy). Here since Foo and Bar are classes that aren't in each other hierarchy, the cast can never succeed.


Generally the cast operator is preferred to the Class#cast method as it's more concise and can be analyzed by the compiler to spit out blatant issues with the code.

Class#cast takes responsibility for type checking at run-time rather than during compilation.

There are certainly use-cases for Class#cast, particularly when it comes to reflective operations.

Since lambda's came to java I personally like using Class#cast with the collections/stream API if I'm working with abstract types, for example.

Dog findMyDog(String name, Breed breed) {
    return lostAnimals.stream()
                      .filter(Dog.class::isInstance)
                      .map(Dog.class::cast)
                      .filter(dog -> dog.getName().equalsIgnoreCase(name))
                      .filter(dog -> dog.getBreed() == breed)
                      .findFirst()
                      .orElse(null);
}

C++ and Java are different languages.

The Java C-style cast operator is much more restricted than the C/C++ version. Effectively the Java cast is like the C++ dynamic_cast if the object you have cannot be cast to the new class you will get a run time (or if there is enough information in the code a compile time) exception. Thus the C++ idea of not using C type casts is not a good idea in Java


In addition to remove ugly cast warnings as most mentioned ,Class.cast is run-time cast mostly used with generic casting ,due to generic info will be erased at run time and some how each generic will be considered Object , this leads to not to throw an early ClassCastException.

for example serviceLoder use this trick when creating the objects,check S p = service.cast(c.newInstance()); this will throw a class cast exception when S P =(S) c.newInstance(); won't and may show a warning 'Type safety: Unchecked cast from Object to S'.(same as Object P =(Object) c.newInstance();)

-simply it checks that the casted object is instance of casting class then it will use the cast operator to cast and hide the warning by suppressing it.

java implementation for dynamic cast:

@SuppressWarnings("unchecked")
public T cast(Object obj) {
    if (obj != null && !isInstance(obj))
        throw new ClassCastException(cannotCastMsg(obj));
    return (T) obj;
}




    private S nextService() {
        if (!hasNextService())
            throw new NoSuchElementException();
        String cn = nextName;
        nextName = null;
        Class<?> c = null;
        try {
            c = Class.forName(cn, false, loader);
        } catch (ClassNotFoundException x) {
            fail(service,
                 "Provider " + cn + " not found");
        }
        if (!service.isAssignableFrom(c)) {
            fail(service,
                 "Provider " + cn  + " not a subtype");
        }
        try {
            S p = service.cast(c.newInstance());
            providers.put(cn, p);
            return p;
        } catch (Throwable x) {
            fail(service,
                 "Provider " + cn + " could not be instantiated",
                 x);
        }
        throw new Error();          // This cannot happen
    }

It's always problematic and often misleading to try and translate constructs and concepts between languages. Casting is no exception. Particularly because Java is a dynamic language and C++ is somewhat different.

All casting in Java, no matter how you do it, is done at runtime. Type information is held at runtime. C++ is a bit more of a mix. You can cast a struct in C++ to another and it's merely a reinterpretation of the bytes that represent those structs. Java doesn't work that way.

Also generics in Java and C++ are vastly different. Don't concern yourself overly with how you do C++ things in Java. You need to learn how to do things the Java way.


Personally, I've used this before to build a JSON to POJO converter. In the case that the JSONObject processed with the function contains an array or nested JSONObjects (implying that the data here isn't of a primitive type or String), I attempt to invoke the setter method using class.cast() in this fashion:

public static Object convertResponse(Class<?> clazz, JSONObject readResultObject) {
    ...
    for(Method m : clazz.getMethods()) {
        if(!m.isAnnotationPresent(convertResultIgnore.class) && 
            m.getName().toLowerCase().startsWith("set")) {
        ...
        m.invoke(returnObject,  m.getParameters()[0].getClass().cast(convertResponse(m.getParameters()[0].getType(), readResultObject.getJSONObject(key))));
    }
    ...
}

Not sure if this is extremely helpful, but as said here before, reflection is one of the very few legitimate use case of class.cast() I can think of, at least you have another example now.


Class.cast() is rarely ever used in Java code. If it is used then usually with types that are only known at runtime (i.e. via their respective Class objects and by some type parameter). It is only really useful in code that uses generics (that's also the reason it wasn't introduced earlier).

It is not similar to reinterpret_cast, because it will not allow you to break the type system at runtime any more than a normal cast does (i.e. you can break generic type parameters, but can't break "real" types).

The evils of the C-style cast operator generally don't apply to Java. The Java code that looks like a C-style cast is most similar to a dynamic_cast<>() with a reference type in Java (remember: Java has runtime type information).

Generally comparing the C++ casting operators with Java casting is pretty hard since in Java you can only ever cast reference and no conversion ever happens to objects (only primitive values can be converted using this syntax).


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to generics

Instantiating a generic type Are these methods thread safe? The given key was not present in the dictionary. Which key? Using Java generics for JPA findAll() query with WHERE clause Using Spring RestTemplate in generic method with generic parameter How to create a generic array? Create a List of primitive int? How to have Java method return generic list of any type? Create a new object from type parameter in generic class What is the "proper" way to cast Hibernate Query.list() to List<Type>?

Examples related to casting

Subtracting 1 day from a timestamp date Cast object to interface in TypeScript TypeScript enum to object array Casting a number to a string in TypeScript Hive cast string to date dd-MM-yyyy Casting int to bool in C/C++ Swift double to string No function matches the given name and argument types C convert floating point to int PostgreSQL : cast string to date DD/MM/YYYY

Examples related to compiler-warnings

Property getters and setters error C2220: warning treated as error - no 'object' file generated Objective-C implicit conversion loses integer precision 'NSUInteger' (aka 'unsigned long') to 'int' warning How do you disable the unused variable warnings coming out of gcc in 3rd party code I do not wish to edit? What is "android:allowBackup"? Why this "Implicit declaration of function 'X'"? How to compile without warnings being treated as errors? warning: implicit declaration of function Multi-character constant warnings What does "control reaches end of non-void function" mean?