简体   繁体   中英

Guava TypeToken and generic classes

I'm using Guava TypeToken class in my project, but I'm getting an unexpected result.

I have MyGenericClass<T> :

public class MyGenericClass<T> implements MyInterface {

    private TypeToken<T> recordType;

    public MyGenericClass(String name) {
        this.recordType = new TypeToken<T>(getClass()) {};

        // ...
    }

    // ...

    @SuppressWarnings("unchecked")
    protected Class<T> getRecordType() {
        return (Class<T>) recordType.getRawType();
    }
}

So if I instantiate an object via new MyGenericClass<String>() and then invoke getRecordType() I expect to get java.lang.String , instead I'm getting java.lang.Object .

But, if I extend generic class:

public class MyStringImpl extends  MyGenericClass<String> {
    // ...
}

and instantiate this new class: new MyStringImpl() then I get the correct result.

Why is this happening? Is this the expected behaviour of TypeToken ?

To add some boring details to Ian's answer: It would be nice if TypeToken worked the way you expected, but this is impossible. When you declare

public class MyGenericClass<T> implements MyInterface {...}

the JVM sees something like

public class MyGenericClass<Object> implements MyInterface {...}

due to erasure.

But when you declare

public class MyStringImpl extends MyGenericClass<String> {...}

then in the definition of MyStringImpl the generics used are recorded and can be obtained via Class#getGenericSuperclass() . That's (a part of) the magic behind TypeToken .

To make this work you need the same anonymous subclass trick when you instantiate MyGenericClass :

new MyGenericClass<String>() {}

If you do that then you will get String returned by getRecordType . The reason why this is necessary is explained in the JavaDocs for that TypeToken constructor .

Clients create an empty anonymous subclass. Doing so embeds the type parameter in the anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM