Dynamic Casting with Generics: Type Erasure Problems

Discussion in 'Java' started by William, Mar 3, 2011.

  1. William

    William Guest

    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?
     
    William, Mar 3, 2011
    #1
    1. Advertising

  2. On 03/03/2011 11:12 AM, William wrote:
    > 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.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
     
    Joshua Cranmer, Mar 3, 2011
    #2
    1. Advertising

  3. William

    markspace Guest

    On 3/3/2011 8:12 AM, William wrote:

    > 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;
    }
    }
     
    markspace, Mar 3, 2011
    #3
  4. William

    Lew Guest

    On Mar 3, 11:34 am, markspace <-@.> wrote:
    > On 3/3/2011 8:12 AM, William wrote:
    >
    > > 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;
    >              }
    >          }


    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.

    --
    Lew
     
    Lew, Mar 3, 2011
    #4
  5. William

    markspace Guest

    On 3/3/2011 8:55 AM, Lew wrote:

    > On Mar 3, 11:34 am, markspace<-@.> wrote:
    >> T convertToT(Object object)
    >> {
    >> // just cast
    >> return (T) object;


    > 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.
     
    markspace, Mar 3, 2011
    #5
  6. William

    Lew Guest

    On Mar 3, 12:54 pm, markspace <-@.> wrote:
    > On 3/3/2011 8:55 AM, Lew wrote:
    >
    > > On Mar 3, 11:34 am, markspace<-@.>  wrote:
    > >>               T convertToT(Object object)
    > >>               {
    > >>                   // just cast
    > >>                   return (T) object;

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


    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.

    --
    Lew
     
    Lew, Mar 3, 2011
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sebastian Millies

    Java Generics, Type Erasure and Frameworks

    Sebastian Millies, Oct 7, 2004, in forum: Java
    Replies:
    1
    Views:
    653
    Chris Uppal
    Oct 7, 2004
  2. z-man
    Replies:
    8
    Views:
    372
    Thomas Weidenfeller
    Oct 9, 2006
  3. Martin Lorentzson

    Generics and type erasure

    Martin Lorentzson, Nov 5, 2006, in forum: Java
    Replies:
    2
    Views:
    422
    Martin Lorentzson
    Nov 6, 2006
  4. William
    Replies:
    3
    Views:
    654
    Andreas Leitgeb
    Mar 4, 2011
  5. William
    Replies:
    16
    Views:
    470
Loading...

Share This Page