tags:

views:

1506

answers:

5

Looking through some code I came across the following code

trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto));

and I'd like to know if casting this way has any advantages over

trTuDocPackTypdBd.update((TrTuDocPackTypeDto)packDto);

I've asked the developer responsible and he said he used it because it was new (which doesn't seem like a particularly good reason to me), but I'm intrigued when I would want to use the method.

A: 

Both of these statements are identical. Pick whichever one you find more readable. The second method is more common in my experience, and it is the once that I prefer.

I tend to use the cast method solely when I am working with reflection, and it reads nicer in that situation. All other times I find myself using the second way of casting.

Rontologist
+1  A: 

The main case for doing it (IME) is when you need to safely cast in a generic class/method. Due to type erasure, you can't cast to T but if you've been provided a Class<? extends T> parameter then you can use that to cast and the result will be assignable to a variable of type T.

Jon Skeet
+9  A: 

These statements are not identical. The cast method is a normal method invocation (invokevirtual JVM instruction) while the other is a language construct (checkcast instruction). In the case you show above, you should use the second form: (TrTuDocPackTypeDto) packDto

The cast method is used in reflective programming with generics, when you have a Class instance for some variable type. You could use it like this:

public <T> Set<T> find(Class<T> clz, Filter criteria) {
  List<?> raw = session.find(clz, criteria); /* A legacy, un-generic API. */
  Set<T> safe = new HashSet<T>();
  for (Object o : raw) 
    safe.add(clz.cast(o));
  return safe;
}

This gives you a safe way to avoid the incorrect alternative of simply casting a raw type to a generic type:

/* DO NOT DO THIS! */
List raw = new ArrayList();
...
return (List<Widget>) raw;

The compiler will warn you, Unchecked cast from List to List<Widget>, meaning that in the ellipsis, someone could have added a Gadget to the raw list, which will eventually cause a ClassCastException when the caller iterates over the returned list of (supposed) Widget instances.

erickson
On a quick scan of the Language Reference, it appears that the `class.cast()` would bypass the 'unsafe conversion` warning the compiler would normally display.As ericksonsaid, use the language construct until you can't. ;-)
Ken Gentle
Can you explain what you SHOULD do in the second case? I just ran into this compiler warning yesterday but ignored it because I'm lazy. Are you suggesting something like List<Widget>.cast(raw)?
Outlaw Programmer
@Outlaw -- to avoid the second case, you need to use something like I provided in the "find" method above. That is, you need to iterate over the `List` and test that each element really is a `Widget`. Then, it would be alright to ignore the warning that you get from "(List<Widget>) raw".
erickson
A: 

I can't find an example where the cast method is possible and the cast syntax not. However, looking at the code, it seems that in case the cast is not possible, the cast method throws a ClassCastException with no type information attached, whereas the cast syntax will give you some hints (as in, "could not cast Snoopy to TyrannosorusRex") :

/**
 * Casts an object to the class or interface represented
 * by this <tt>Class</tt> object.
 *
 * @param obj the object to be cast
 * @return the object after casting, or null if obj is null
 *
 * @throws ClassCastException if the object is not
 * null and is not assignable to the type T.
 *
 * @since 1.5
 */
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
    throw new ClassCastException();
return (T) obj;
}
phtrivier
Class.cast() is useful if you don't know what class you're casting to yet (i.e., reflection and so forth). Generally, you'd first check Class.isInstance(Object) to make sure you won't get a CCE.
Michael Myers
A: 

With the first form

trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto));

you can do this:

public void dynamicCast( Class clazz, Object o ) { 
     this.x = clazz.cast( o );
}

With the second you can't. The casting class should be hard coded.

Why would you use a variable to cast in first place? That's another question. :) The first thing that comes to mind is, you don't know ( at compile time ) the class that will be casted to.

OscarRyz