How to do `MyClass.class` in Java?

前端 未结 6 1262
有刺的猬
有刺的猬 2020-12-15 21:46

How can call public T doit(Class clazz); using MyClass.class as clazz where I can not instantiate or extend MyClas

相关标签:
6条回答
  • 2020-12-15 22:08

    How to do MyClass<String>.class in Java?

    You can't.

    Generics in Java use type erasure; the type of the parametrized argument is enforced during compilation, but it is lost after compilation. The resulting byte code for an instance of a generic class does not contain any run-time meta-data on its arguments whatsoever.

    As it is now, it is just not possible, a major language design blunder IMO.

    0 讨论(0)
  • 2020-12-15 22:19

    T corresponds to List, so any reference to String as the generic paramter of List is irrelevant.

    0 讨论(0)
  • 2020-12-15 22:21

    Use List.class. Because of type erasure type parameters to Java classes are entirely a compile-time construct - even if List<String>.class was valid syntax, it would be the exact same class as List<Date>.class, etc. Since reflection is by nature a runtime thing, it doesn't deal well with type parameters (as implemented in Java).

    If you want to use the Class object to (for example) instantiate a new List instance, you can cast the result of that operation to have the appropriate type parameter.

    List<String> list = (List<String>)(ArrayList.class.newInstance());
    
    0 讨论(0)
  • 2020-12-15 22:23

    I've seen similar questions asked several times, for example Acquiring generic class type

    There are legitimate reasons to construct static generic types. In op' case, he would probably like to

    MyClass<String> result = doit(MyClass<String>.class);
    

    Without language syntax support, casting is the correct way to go. If this is needed quite often, the casting should be put in a method, as

    public class MyClass<T>
    {
        @SuppressWarnings("unchecked")
        // may need a better method name
        static public <T2> Class<MyClass<T2>> of(Class<T2> tClass)
        {
            return (Class<MyClass<T2>>)(Class<?>)(MyClass.class);
        }
    }
    
    MyClass<String> result = doit(MyClass.of(String.class)); // no warning
    

    We can supress the warning on that method alone, after making sure the cast is safe. Any call site will not see the warning.

    This is all compile time casting game. At runtime all the type parameters are erased, and really only the naked class object is passed around. The of method will most likely be optimized off, so to JVM the last line is nothing but

    MyClass result = doit(MyClass.class)
    

    There are also times when at runtime we need a complete MyClass<String> type. A ParameterizedType object needs to be obtained to represent MyClass<String>.

    When the two requirements are combined together, that is, we need a compile time expression regarding MyClass and String that will evaluate at runtime to a ParameterizedType

    ParameterizedType type_MyClass_String = ???? MyClass ?? String ???
    

    There is a technique involving an anonymous subclass of MyClass<String>

    ParameterizedType type_MyClass_String = superTypeOf( new MyClass<String>(){} );
    

    which I find quite disturbing.

    0 讨论(0)
  • 2020-12-15 22:26

    Since after your update your question does not appear to be an exact duplicate:

    You would need to call getClass() on an instance of MyClass. Better have a dummy static final instance somewhere:

    public static final MyClass INSTANCE = new MyClass();
    ...
    return (Class<MyClass<String>>) instance.getClass();
    
    0 讨论(0)
  • 2020-12-15 22:27

    See http://jackson.codehaus.org/1.7.0/javadoc/org/codehaus/jackson/type/TypeReference.html and the references that it references for a comprehensive discussion of the issues around generics.

    the bottom line is that, if you really want to work with generic types in this way, you have to stop using Class and start using Type and its subclasses.

    Contrary to your comment on another answer, you can write List<List<String>> obj = (List<List<String>>) doit(List.class);, you just can't avoid a warning when you write it.

    0 讨论(0)
提交回复
热议问题