tags:

views:

213

answers:

5

What is the difference between these two ways of casting in Java?

  1. (CastingClass) objectToCast;

  2. CastingClass.class.cast(objectToCast);

The source of Class#cast(Object) is as follows:

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

So, cast is basically a generic wrapper of the cast operation, but I still don't understand why you would need a method for it.

+3  A: 

Because you cannot just write (T)objectToCast, when T is a generic type parameter (due to type erasure). Java compiler will let you do that, but T will be treated as Object there, so the cast will always succeed, even if the object you're casting isn't really an instance of T.

Pavel Minaev
Hi Pavel, would you mind explaining this a little more? `cast` appears to do just that: `return (T) obj;`
simmbot
You can most certainly write that. It merely emits a compiler warning.
meriton
@meriton: good point, edited. What I wanted to say is that the cast still won't do what it should really do.
Pavel Minaev
@simmbot: it does, but it also does an explicit type check before doing that (since the cast itself won't do that). So it's just as typesafe as a normal `(Type)object` cast - it will only return a reference of type `T` if the object actually extends or implements `T`, and otherwise it will throw.
Pavel Minaev
+5  A: 

You can only use the first form for statically linked classes.

In many cases that's not enough - for example, you may have obtained class instance using reflection or it was passed to your method as parameter; hence the second form.

ChssPly76
Right. In the first form, you're "baking" the cast in the source code. You can't change it without recompiling.The second form allows you to try to cast to an arbitrary class.
Noel Ang
+2  A: 

This first is an ordinary cast. It requires that the type to cast to is known at compile time. It verifies at compile time that the cast can be correct, and checks (if the type to cast to is not generic) that the cast is correct at runtime.

The second uses the reflection api. It requires that the class to cast to is known at runtime. It doesn't verify anything at compile time, but always checks that the cast is correct at runtime.

Type parameters are only known at compile type, hence you can not use the second approach for a type parameter (the expression T.class does not compile).

Dynamically loaded classes (for instance with Class.forName(String)) are only known at runtime, hence the first approach can not be used.

Edit: However, as Pavel points out, it makes no sense to cast to a dynamically loaded class. I agree that the only real usefulness of Class.cast(Object) is to cast to a type parameter for which you happen to have a class object available.

If the type to cast to does not contain a type parameter, the first approach is better, as the additional compile time checking can catch bugs, you lose no type safety at runtime, and get a shorter syntax to boot.

meriton
For dynamically loaded classes, though, why would you need a cast at all? A cast is usually to force the expression to have some type, but you don't know the type in advance in case of dynamically loaded classes. After all, if you have a dynamically loaded class, you don't know what `T` is in the call to `Class<T>.cast()`, so you'd just use the raw version, and then the return type would be `Object` - not much of a cast. It would check for type, but surely `Class.isInstance()` is a better way to do the same. All in all, it really seems to me that this is intended for generics only.
Pavel Minaev
You're right. Have edited my answer accordingly.
meriton
A: 

Here you can find an use example wherein Class#cast() is used. It may give new insights.

BalusC
+1  A: 

In the first one you have to hardcode the casting class.

( ClassToCast ) objectToCast;

In the second one the casting class maybe a parameter:

Class toCast = getClassToCast();

toCast.cast( objectToCast );
OscarRyz