20

I recently stumbled upon a piece of code that went like this:

Object o = .. ;
Foo foo = Foo.class.cast(o);

I was actually not even aware that java.lang.Class had a cast method, so I looked into the docs, and from what I gather this does simply do a cast to the class that the Class object represents. So the code above would be roughly equivalent to

Object o = ..;
Foo foo = (Foo)o;

So I wondered, why I would want to use the cast method instead of simply doing a cast "the old way". Has anyone a good example where the usage of the cast method is beneficial over doing the simple cast?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Jan Thomä
  • 13,296
  • 6
  • 55
  • 83

8 Answers8

8

I don't think it's often used exactly as you have shown. Most common use I have seen is where folks using generics are trying to do the equivalent of this:

public static <T extends Number> T castToNumber(Object o) {
    return (T)o;
}

Which doesn't really do anything useful because of type erasure.

Whereas this works, and is type safe (modulo ClassCastExceptions):

public static <T extends Number> T castToNumber(Object o, Class<T> clazz) {
    return clazz.cast(o);
}

EDIT: Couple of examples of use from google guava:

clstrfsck
  • 14,715
  • 4
  • 44
  • 59
  • This is still equivalent to `(Number) o` since a cast has no influence over the actual type of an object. – nfechner Oct 26 '11 at 08:51
  • 1
    Not really, but keep in mind this is a simplified example, and usually `o` and `clazz` would be determined at runtime, rather than hardcoded. `Integer x = castToNumber(o, Integer.class)` is valid here, but `Integer x = (Number)o` wouldn't be. Maybe I should have left off the `Number` bit for the example? Maybe `castToNumber` was a bad choice for method name? – clstrfsck Oct 26 '11 at 08:56
  • The point I'm trying to make is, that you still need to have a left side to your assignment, where you need to state an explicit class. So you can always simply write `T x = (T) o;` – nfechner Oct 26 '11 at 09:09
  • I meant `T` as a general placeholder for any class you might think about, not as a generics construct. In terms of real code like this: `Object o = new Object(); Integer i = (Integer) o;` Obviously this code will throw a `ClassCastException` at runtime, but it will show no compiler warning. – nfechner Oct 26 '11 at 09:23
  • I misunderstood your response for a moment, but I think I understand now. Your comment is reasonable for client code, but if you are writing a library, it's not always clear exactly what the uses are going to be. I've added a couple of concrete uses from guava libs. – clstrfsck Oct 26 '11 at 09:28
4

In Java there is often more than one way to skin a cat. Such functionality may be useful in cases where you have framework code. Imagine a method which accepts a Class object instance and an Object instance and returns the Object case as the class:

public static void doSomething(Class<? extends SomeBaseClass> whatToCastAs,Object o)
    {
        SomeBaseClass castObj =  whatToCastAs.cast(o);
        castObj.doSomething();
    }

In general, use the simpler casting, unless it does not suffice.

Krystian Cybulski
  • 10,789
  • 12
  • 67
  • 98
  • You're kidding, right? Why would you not simply write `((SomeBaseClass) o).doSomething();`? – nfechner Oct 26 '11 at 08:47
  • @nfechner, because you can't always do that. I guess the best example is for (part of) an implementation of the JDBC public T unwrap(Class iface) method. There you could do something like: return iface.cast(this); – Mark Rotteveel Oct 26 '11 at 10:18
  • 1
    (CastTarget)o is compile time, foo.getClass().cast(0) is runtime – Konstantin Pribluda Oct 26 '11 at 11:15
2

In some cases, you only know the type to cast an object to during runtime, and that's when you have to use the cast method.

RAY
  • 6,810
  • 6
  • 40
  • 67
2

There is absolutely no reason to write Foo.class.cast(o), it is equivalent to (Foo)o.

In general, if X is a reifiable type, and Class<X> clazz, then clazz.cast(o) is same as (X)o.

If all types are reifiable, method Class.cast() is therefore redundant and useless.

Unfortunately, due to erasure in current version of Java, not all types are reifiable. For example, type variables are not reifiable.

If T is a type variable, cast (T)o is unchecked, because at runtime, the exact type of T is unknown to JVM, JVM cannot test if o is really type T. The cast may be allowed erroneously, which may trigger problems later.

It is not a huge problem; usually when the programmer does (T)o, he has already reasoned that the cast is safe, and won't cause any problem at runtime. The cast is checked by app logic.

Suppose a Class<T> clazz is available at the point of cast, then we do know what T is at runtime; we can add extra runtime check to make sure o is indeed a T.

check clazz.isInstance(o);
(T)o;

And this is essentially what Class.cast() does.

We would never expect the cast to fail in any case, therefore in a correctly implemented app, check clazz.isInstance(o) must always succeed anway, therefore clazz.cast(o) is equivalent to (T)o - once again, under the assumption that the code is correct.

If one can prove that the code is correct and the cast is safe, one could prefer (T)o to clazz.cast(o) for performance reason. In the example of MutableClassToInstanceMap raised in another answer, we can see obviously that the cast is safe, therefore simple (T)o would have sufficed.

irreputable
  • 44,725
  • 9
  • 65
  • 93
  • 1
    "If all types are reifiable, method Class.cast() is therefore redundant and useless." Not true. Class.cast() is necessary when you don't know the class at compile time, and only have a class object at runtime – newacct Oct 26 '11 at 19:39
  • 1
    @newacct If java is fully reifiable, runtime knows the actual type of `T`, so it can check `(T)o` to make sure `o` is indeed of type `T`. There is no need for `Class.cast(o)` then. – irreputable Oct 26 '11 at 21:25
1

class.cast is designed for generics type.

When you construct a class with generic parameter T, you can pass in a Class. You can then do the cast with both static and dynamic checking, which (T) does not give you. It also doesn't produce unchecked warnings, because it is checked (at that point).

aleroot
  • 71,077
  • 30
  • 176
  • 213
1

The common sample for that is when you retrieve from persistent layer a collection of entity referenced with a Class Object and some conditions. The returned collection could contain unchecked objects, so if you just cast it as pointed G_H, you will throw the Cast Exception at this point, and not when the values are accessed.

One example for this is when you retrieve a collection from a DAO that returns an unchecked collection and on your service you iterate over it, this situation can lead to a ClassCastException.

One way to solve it, as you have the wanted class and the unchecked collection is iterate over it and cast it inside the DAO transforming the collection in a checked collection and afterwards return it.

Francisco Spaeth
  • 23,493
  • 7
  • 67
  • 106
0

Because you might have something this:

Number fooMethod(Class<? extends Number> clazz) {
    return clazz.cast(var);
}
G_H
  • 11,739
  • 3
  • 38
  • 82
0

A "cast" in Java, e.g. (Number)var, where the thing inside the parentheses is a reference type, really consists of two parts:

  • Compile time: the result of the cast expression has the type of the type you cast to
  • Run time: it inserts a check operation, which basically says, if the object is not an instance of that class, then throw a ClassCast Exception (if the thing you're casting to is a type variable, then the class it checks would be the lower bound of the type variable)

To use the syntax, you need to know the class at the time you write the code. Suppose you don't know at compile-time what class you want to cast to; you only know it at runtime.

Now you would ask, then what is the point of casting? Isn't the point of casting to turn the expression into the desired type at compile time? So if you don't know the type at compile time, then there is no benefit at compile-time, right? True, but that is just the first item above. You're forgetting the runtime component of a cast (second item above): it checks the object against the class.

Therefore, the purpose of a runtime cast (i.e. Class.cast()) is to check that the object is an instance of the class, and if not, throw an exception. It is roughly equivalent to this but shorter:

if (!clazz.isInstance(var))
    throw new ClassCastException();

Some people have mentioned that Class.cast() also has a nice return type that is based on the type parameter of the class passed in, but that is just a compile-time feature that is provided by a compile-time cast anyway. So for that purpose there is no point in using Class.cast().

newacct
  • 119,665
  • 29
  • 163
  • 224