Dynamic Casting with Generics: Type Erasure Problems

W

William

class IfThisCompiles
{
Cloneable instanceOfObject;

Cloneable convertToCloneable(Object object)
{
return instanceOfObject.getClass().cast(object);
}

}

class WhyDoesntThis<T>
{
T instanceOfT;

T convertToT(Object object)
{
//compiler error: Type mismatch:
//cannot convert from capture#1-of ? extends Object to T
return instanceOfT.getClass().cast(object);
}
}

In both cases, the instance can be a subclass of the class that is defined,but that should be okay, because it only has to honor the parent's interface. There might be a more complex example that illustrates why it should fail, but I'm struggling to come up with one. Any thoughts?
 
J

Joshua Cranmer

In both cases, the instance can be a subclass of the class that is
defined, but that should be okay, because it only has to honor the
parent's interface. There might be a more complex example that
illustrates why it should fail, but I'm struggling to come up with
one. Any thoughts?

If you look at the documentation for getClass(), it says the following:
The actual result type is Class<? extends |X|> where |X| is the erasure
of the static type of the expression on which getClass is called.

In the latter case, you have T, which erases to Object, so the end
result is an expression <? extends Object> as opposed to <? extends T>.

To do what you really want, you have to pass in a Class<T> into the
constructor of the class, and use that to do the typecasting thenceforth.
 
M

markspace

In both cases, the instance can be a subclass of the class that is
defined, but that should be okay, because it only has to honor the
parent's interface.


Yeah, getClass() returns Class<?>, not Class<T>. So they don't match.
Read the docs on methods you don't think are "working."


Fyi, this does work:

class WhyDoesntThis<T>
{
T instanceOfT;

T convertToT(Object object)
{
// just cast
return (T) object;
}
}
 
L

Lew

Yeah, getClass() returns Class<?>, not Class<T>.  So they don't match.
Read the docs on methods you don't think are "working."

Fyi, this does work:

         class WhyDoesntThis<T>
         {
             T instanceOfT;

             T convertToT(Object object)
             {
                 // just cast
                 return (T) object;
             }
         }

Don't you need to '@SuppressWarnings()' and catch the
'ClassCastException'?

Not that you need to-need to, but it's bad practice not to, therefore
you need to.

The tricky thing with wildcards, and Brian Goetz has some excellent
articles about this on DeveloperWorks/java, is that they guarantee a
capture, just not which capture.

So if "? extends T" and you only know "T", you cannot be sure that the
"T" you have will correctly downcast to the capture of the "?". Hence
the error.

"? extends" prevents puts, "? super" prevents gets.
 
M

markspace

Don't you need to '@SuppressWarnings()' and catch the
'ClassCastException'?


True. I just did a quick check with my IDE to verify it would let me do
that without an error. I didn't really think about the ramifications of
casting an Object.
 
L

Lew

True.  I just did a quick check with my IDE to verify it would let me do
that without an error.  I didn't really think about the ramifications of
casting an Object.

I use this stuff a lot in real code. I found the use of a run-time
type token (a 'Class <T>') to be key when run-time typing is
necessary.

You have to know what you're asserting with generics. The mistake
category I commit most often is thinking that I've declared more about
the types than I really have, for example, thinking that "? extends T"
is essentially equivalent to "T". It isn't.

The fact that generics are erased at run-time doesn't mean you cannot
do run-time typing. You just have to be explicit instead of letting
the compiler generate the code for you.
 

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

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top