Class.cast(Object) - what benefit?

R

Raymond DeCampo

Patricia said:
I don't think it's that, because, according to the API documentation, it
throws ClassCastException "if the object is not null and is not
assignable to the type T."

It seems more likely to be something to do with generics, but I haven't
worked out what.

Patricia

The scenario I am imagining is that you have a generic class
parametrized by class T. Somewhere in this class you have an Object
that you want to cast to type T. Presumably the syntax

T t = (T)obj;

is illegal. So one would use the Class.cast() method. Although I'm not
sure how you get an instance of Class<T> in this case.

DISCLAIMER: I haven't worked with generics, so the above may be totally
wrong, misguided and generally rot. Also, I may have used the incorrect
vocabulary.

Ray
 
T

Thomas Hawtin

Raymond said:
The scenario I am imagining is that you have a generic class
parametrized by class T. Somewhere in this class you have an Object
that you want to cast to type T. Presumably the syntax

T t = (T)obj;

is illegal. So one would use the Class.cast() method. Although I'm not
sure how you get an instance of Class<T> in this case.

When you construct a class with generic parameter T, you can pass in a
Class<T>. 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).

Tom Hawtin
 
R

Raymond DeCampo

Thomas said:
When you construct a class with generic parameter T, you can pass in a
Class<T>.

That seems hokey. I expected a more natural mechanism. (Please do not
misinterpret, you are the messenger, I am criticizing the composer of
the message, so to speak.)

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).

Tom Hawtin

Ray
 
R

Roedy Green

When you construct a class with generic parameter T, you can pass in a
Class<T>. 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).

I'll do some decompilation to verify this if someone has not already.


Is there ANY run time code that protects a typed ArrayList from
getting the wrong objects in it? I presume not. It is fully type
erased.

There must be a run-time cast somewhere when you take Objects out of
the typed ArrayList. I presume the compiler inserts these after a get
call. They are part of the calling code, not the ArrayList.

These casts were necessary even if you had 100% confidence they would
always succeed.
 
J

John C. Bollinger

Ian said:
I see it used, but there's no explanation of why it's there. The best
I can figure out, it's just a shortcut for:

if (!cls.isInstance(o))
throw new ClassCastException(...)

No, you're missing the point, which is that the cast can be typechecked
at compile time. More specifically, the cast of an object of generic
type can be typechecked at compile time, making it possible to avoid an
"unchecked cast" warning and *ensure* that no ClassCastException will be
thrown.

Example [Not tested]:

class ListHolder <T> {

private List<T> list;

// ...

public <S> S getElement(Class<S> clazz, int i) {

// Compatibility of S and T checked at compile time,
// on a per-invocation basis:

return clazz.cast(list.get(i));
}
}


Note that two distinct type parameters are involved in my example; I
can't imagine Class.cast() being useful with fewer.
 
I

Ingo R. Homann

Hi,
public <S> S getElement(Class<S> clazz, int i) {
^^^ ^^^
But that means that you have to pass the Type-Parameter (S) twice which
is not a good idea!

And "S.class" doesn't work.

Ciao,
Ingo
 
T

Thomas Hawtin

Ingo said:
Well, now, then how do you call it?

class MyCLass {
String myFunc(ListHolder<CharSequence> listHolder) {
return listHolder.getElement(String.class, 0);
}
}

Tom Hawtin
 
I

Ingo R. Homann

Hi,

Thomas said:
class MyCLass {
String myFunc(ListHolder<CharSequence> listHolder) {
return listHolder.getElement(String.class, 0);
}
}

Eh, I think it must be

listHolder.<String>getElement(String.class, 0);

to get no warning.

Ciao,
Ingo
 
T

Thomas Hawtin

Ingo said:
Eh, I think it must be

listHolder.<String>getElement(String.class, 0);

to get no warning.

Nope. The type is inferred. Same as with EnumSet.of.

I have tried that exact code on 1.5.0-b64, 1.5.0_04-b05 and
1.6.0-ea-b48. It compiles without a whisper.

Tom Hawtin
 
I

Ingo R. Homann

Hi,

Thomas said:
Nope. The type is inferred. Same as with EnumSet.of.

I have tried that exact code on 1.5.0-b64, 1.5.0_04-b05 and
1.6.0-ea-b48. It compiles without a whisper.

I just tried it with Eclipse 3.1 final (which I admit is not such a good
reference-implementation as your different JDKs) and...

....it compiles without a whisper.

Very interesting, I never expected that!

Thanks,
Ingo
 
I

Ian Pilcher

John said:
No, you're missing the point, which is that the cast can be typechecked
at compile time. More specifically, the cast of an object of generic
type can be typechecked at compile time, making it possible to avoid an
"unchecked cast" warning and *ensure* that no ClassCastException will be
thrown.

I've tested and enhanced your example a little bit, and I may see the
point, but I surely don't agree with it.

package temp;

import java.util.*;

class ListHolder<T>
{
private List<T> list;

public ListHolder(List<T> list)
{
this.list = list;
}

public <S> S getElementAs(Class<S> cls, int i)
{
return cls.cast(list.get(i)); // no warning
// return (S)(list.get(i)); // warning
}
}

class Cast
{
public static void main(String[] args)
{
List<Integer> list = new LinkedList<Integer>();
list.add(new Integer(0));
ListHolder<Integer> holder = new ListHolder<Integer>(list);

// This is compatible
Object o = holder.getElementAs(Object.class, 0);

// This is not
List l = holder.getElementAs(List.class, 0);
}
}

You're right that the Class.cast form does not throw an "unchecked cast"
warning, and the normal cast does. That seems to be the only
difference, however, and you've provided a perfect example of why this
warning is stupid in the first place.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top