Get generic type of class at runtime

后端 未结 26 2514
野的像风
野的像风 2020-11-21 04:40

How can I achieve this?

public class GenericClass
{
    public Type getMyType()
    {
        //How do I return the type of T?
    }
}
相关标签:
26条回答
  • 2020-11-21 05:11
    public abstract class AbstractDao<T>
    {
        private final Class<T> persistentClass;
    
        public AbstractDao()
        {
            this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
                    .getActualTypeArguments()[0];
        }
    }
    
    0 讨论(0)
  • 2020-11-21 05:14

    I used follow approach:

    public class A<T> {
    
        protected Class<T> clazz;
    
        public A() {
            this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
    
        public Class<T> getClazz() {
            return clazz;
        }
    }
    
    public class B extends A<C> {
       /* ... */
        public void anything() {
           // here I may use getClazz();
        }
    }
    
    0 讨论(0)
  • 2020-11-21 05:16

    As others mentioned, it's only possible via reflection in certain circumstances.

    If you really need the type, this is the usual (type-safe) workaround pattern:

    public class GenericClass<T> {
    
         private final Class<T> type;
    
         public GenericClass(Class<T> type) {
              this.type = type;
         }
    
         public Class<T> getMyType() {
             return this.type;
         }
    }
    
    0 讨论(0)
  • 2020-11-21 05:16

    I think there is another elegant solution.

    What you want to do is (safely) "pass" the type of the generic type parameter up from the concerete class to the superclass.

    If you allow yourself to think of the class type as "metadata" on the class, that suggests the Java method for encoding metadata in at runtime: annotations.

    First define a custom annotation along these lines:

    import java.lang.annotation.*;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface EntityAnnotation {
        Class entityClass();
    }
    

    You can then have to add the annotation to your subclass.

    @EntityAnnotation(entityClass =  PassedGenericType.class)
    public class Subclass<PassedGenericType> {...}
    

    Then you can use this code to get the class type in your base class:

    import org.springframework.core.annotation.AnnotationUtils;
    .
    .
    .
    
    private Class getGenericParameterType() {
        final Class aClass = this.getClass();
        EntityAnnotation ne = 
             AnnotationUtils.findAnnotation(aClass, EntityAnnotation.class);
    
        return ne.entityClass();
    }
    

    Some limitations of this approach are:

    1. You specify the generic type (PassedGenericType) in TWO places rather than one which is non-DRY.
    2. This is only possible if you can modify the concrete subclasses.
    0 讨论(0)
  • 2020-11-21 05:16

    If you have a class like:

    public class GenericClass<T> {
        private T data;
    }
    

    with T variable, then you can print T name:

    System.out.println(data.getClass().getSimpleName()); // "String", "Integer", etc.
    
    0 讨论(0)
  • 2020-11-21 05:18

    You can't. If you add a member variable of type T to the class (you don't even have to initialise it), you could use that to recover the type.

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