在运行时获取类的通用类型


508

我该如何实现?

public class GenericClass<T>
{
    public Type getMyType()
    {
        //How do I return the type of T?
    }
}

到目前为止,我尝试过的所有操作始终返回类型,Object而不是所使用的特定类型。


3
@SamuelVidal这不是.NET,这是Java。
Frontear '19

Answers:


317

正如其他人所提到的,只有在某些情况下才能通过反思来实现。

如果您确实需要类型,这是通常的(类型安全)解决方法:

public class GenericClass<T> {

     private final Class<T> type;

     public GenericClass(Class<T> type) {
          this.type = type;
     }

     public Class<T> getMyType() {
         return this.type;
     }
}

58
我喜欢这个答案,但是实例化有点麻烦:GenericClass <AnotherClass> g = new GenericClass <AnotherClass>(AnotherClass.class);
Eliseo Ocampos 2013年

1
如果您使用dao / factory / manager方法,则更加冗长。Foo foo1 = GetDao<Foo>(Foo.class).get(Foo.class, 1)
djmj

2
没错,但是在像容器/反射实例化的无状态远程bean那样的所有情况下都无法正常工作。
djmj 2014年

6
就像我之前的评论的后续文章一样,在经历了很多痛苦的思考之后,我最终使用了这个答案。
托马什Zato -恢复莫妮卡

18
您可以通过提供通用的静态工厂方法来避免多余的引用。类似的东西public static <T> GenericClass<T> of(Class<T> type) {...},然后这样称呼:GenericClass<String> var = GenericClass.of(String.class)。好一点
Joeri Hendrickx

262

我看过这样的东西

private Class<T> persistentClass;

public Constructor() {
    this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
 }

休眠的GenericDataAccessObjects示例中


84
该技术在直接超类上定义了类型参数的情况下有效,但如果在类型层次结构中的其他位置定义了类型参数,则该技术将失败。为了处理更复杂的情况,可以使用诸如TypeTools之类的东西。该文档包含一个更复杂的通用DAO的示例。
乔纳森

25
这仅返回当CLASS实现/扩展具有泛型声明的某些东西时使用的实际类型参数,而不返回实例化INSTANCE时使用的实际类型参数。换句话说,它CAN告诉中class A implements Comparable<String>,实际类型参数String,但它CAN NOT告诉中Set<String> a = new TreeSet<String>(),实际类型参数String。实际上,如其他答案中所述,类型参数信息在编译后会被“擦除”。
小清庞-明日香贤治

32
我正在java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType寻找这个答案。
托马什Zato -恢复莫妮卡

4
Class-Mate杰克逊人也可以使用这种方法。我在这里写下了要点gist.github.com/yunspace/930d4d40a787a1f6a7d1
yunspace 2015年

5
@TomášZato简单地调用上面的代码对我返回了相同的异常。我知道已经有点晚了,但是无论如何,就我而言,我不得不打电话(Class<T>) ((ParameterizedType)getClass().getSuperclass().getGenericSuperclass()).getActualTypeArguments()来获取实际的类型参数。
AndrewMcCoist

98

泛型不是物化在运行时。这意味着该信息在运行时不存在。

在保持向后兼容性的同时将泛型添加到Java是一个巡视的力量(您可以查看关于它的开创性文章:使过去变得更安全:向Java编程语言中添加泛型)。

关于这一主题的文献很多,有些人目前的状态不满意,有人说这实际上是一种诱饵,没有真正的需求。您可以阅读两个链接,我发现它们很有趣。


179
当然,我们不满意,.NET具有更好的通用处理机制
Pacerier 2012年

6
@Pacerier:但是仅靠泛型的泛型并不能使Java达到.NET的水平。值类型的专用代码至少对同等重要,因为.NET为什么在泛型方面更好。
约阿希姆·绍尔

@JoachimSauer,是值类型。我一直想用Java。顺便说一句,专业代码是什么意思?
Pacerier

3
@ spaaarky21不,在编译过程中会删除泛型类型参数(所谓的“擦除”,您可以在Google上搜索它)。只有当超类的类型参数是静态已知时,FrVaBe的答案才有效(请参阅Johnathn的第一篇评论)
ewernli 2014年

1
Java类型擦除是一个历史性的设计缺陷。为了解决这个问题,已经编写了更多的代码来实现它。
Abhijit Sarkar '18

68

使用番石榴。

import com.google.common.reflect.TypeToken;
import java.lang.reflect.Type;

public abstract class GenericClass<T> {
  private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) { };
  private final Type type = typeToken.getType(); // or getRawType() to return Class<? super T>

  public Type getType() {
    return type;
  }

  public static void main(String[] args) {
    GenericClass<String> example = new GenericClass<String>() { };
    System.out.println(example.getType()); // => class java.lang.String
  }
}

前阵子,我贴了一些功能完善的例子包括抽象类和子类在这里

注意:这要求您实例化的子类GenericClass以便它可以正确绑定type参数。否则,它只会将类型返回为T


3
注意,我创建了一个空的匿名子类(请参见最后的两个大括号)。这使用反射来对抗Java的运行时类型擦除。您可以在此处了解更多信息:code.google.com/p/guava-libraries/wiki/ReflectionExplained
Cody A. Ray

3
@ CodyA.Ray您的代码抛出java.lang.IllegalArgumentException: class com.google.common.reflect.TypeToken isn't parameterized。因此我将线路更改new TypeToken(getClass()) { }new TypeToken<T>(getClass()) { }。现在,代码可以正常运行,但Type仍为'T'。看到这个:gist.github.com/m-manu/9cda9d8f9d53bead2035
Manu Manjunath

3
@Dominik请参阅更新后的示例,您可以复制和粘贴该示例以进行自我测试。我还添加了一条注释,阐明您必须实例化一个子类(如图所示)。作为一般礼节的建议,在您指责“一厢情愿”之前,请阅读任何链接的文章和相关的javadocs。我已经多次使用类似的生产代码。我要演示的Guava帮助器适用于此确切的用例,而他们的javadocs几乎显示了该问题的确切答案。docs.guava-libraries.googlecode.com/git/javadoc/com/google/...
科迪A.雷

1
这个答案在Java8上非常有用-我有一个接口和一个工厂类来发出各种类型,并且希望用户能够轻松确定类型。在我的界面中,我添加了默认方法: default Type getParameterType() { final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {}; final Type type = typeToken.getType(); return type; }
理查德·桑德

2
@ CodyA.Ray既然这仅适用于的子类GenericClass,则应使该类成为abstract正确的用法,以免编译错误。
马丁

37

你当然可以。

出于向后兼容的原因,Java 在运行时不使用该信息。但是该信息实际上以元数据形式存在,并且可以通过反射来访问(但仍不用于类型检查)。

通过官方API:

http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29

但是,对于您的情况,我不会使用反射。我个人更倾向于将其用于框架代码。在您的情况下,我只是将类型添加为构造函数参数。


10
getActualTypeArguments仅返回直接类的类型参数。如果您有一个复杂的类型层次结构,其中T可以在层次结构中的任何位置进行参数化,则需要做一些工作来弄清楚它是什么。这或多或少是TypeTools所做的。
乔纳森

36

Java泛型大部分在编译时,这意味着类型信息在运行时会丢失。

class GenericCls<T>
{
    T t;
}

将被编译成类似

class GenericCls
{
   Object o;
}

为了在运行时获取类型信息,您必须将其添加为ctor的参数。

class GenericCls<T>
{
     private Class<T> type;
     public GenericCls(Class<T> cls)
     {
        type= cls;
     }
     Class<T> getType(){return type;}
}

例:

GenericCls<?> instance = new GenericCls<String>(String.class);
assert instance.getType() == String.class;

9
private final Class<T> type;
naXa 2014年

如何从中创建数组类型:Type t = //String[]
Pawel Cioch 2015年

@PawelCioch java.lang.reflect.Array.newInstance(elementtype,length); 希望这有助于(javadoc的可以在这里找到docs.oracle.com/javase/8/docs/api/java/lang/reflect/...
josefx

@PawelCioch缺少一个.getClass()来从创建的数组中获取类型。似乎没有直接获得数组类的方法。大多数Java集合只使用Object []。
josefx 2015年

23
public abstract class AbstractDao<T>
{
    private final Class<T> persistentClass;

    public AbstractDao()
    {
        this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
                .getActualTypeArguments()[0];
    }
}

3
我赞成这个答案,因为它是一种适用于所问问题的解决方案。但是,对于那些想要像我一样在一个类层次结构中向上导航的人,有一个以上的Generic类,这是行不通的。因为您将获得java.lang.object而不是实际的类。
KMC

3
请注意,只有拥有通用类型的类为ABSTRACT时,此解决方案才有效
BabaNew

不适用于Java 11中的抽象类
JRA_TLL

@JRA_TLL您显然做错了。我只是将其与Java 12一起使用,并且就像一个魅力。
Googie

如果要在视图层次结构中向上导航,可以将genericSuperclass强制转换为Class <*>并获取genericSuperclass。最好是循环。
fupduck

21

我使用了以下方法:

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();
    }
}

9
我收到带有此示例代码的“线程“主”中的异常java.lang.ClassCastException:无法将java.lang.Class
强制转换

16

我认为您可以,Java在编译时使用了类型擦除,因此您的代码与预先创建的应用程序和库兼容。

从Oracle文档中:

类型擦除

Java语言引入了泛型,以在编译时提供更严格的类型检查并支持泛型编程。为了实现泛型,Java编译器将类型擦除应用于:

如果类型参数不受限制,则将通用类型中的所有类型参数替换为其边界或对象。因此,产生的字节码仅包含普通的类,接口和方法。必要时插入类型转换,以保持类型安全。生成桥接方法以在扩展的泛型类型中保留多态。类型擦除可确保不会为参数化类型创建新的类;因此,泛型不会产生运行时开销。

http://docs.oracle.com/javase/tutorial/java/generics/erasure.html


朱普,那是不可能的。Java需要经过修饰的泛型才能正常工作。
亨宁

15

Ian Robertson本文中描述的技术对我有效。

简而言之,就是一个肮脏的例子:

 public abstract class AbstractDAO<T extends EntityInterface, U extends QueryCriteria, V>
 {
    /**
     * Method returns class implementing EntityInterface which was used in class
     * extending AbstractDAO
     *
     * @return Class<T extends EntityInterface>
     */
    public Class<T> returnedClass()
    {
        return (Class<T>) getTypeArguments(AbstractDAO.class, getClass()).get(0);
    }

    /**
     * Get the underlying class for a type, or null if the type is a variable
     * type.
     *
     * @param type the type
     * @return the underlying class
     */
    public static Class<?> getClass(Type type)
    {
        if (type instanceof Class) {
            return (Class) type;
        } else if (type instanceof ParameterizedType) {
            return getClass(((ParameterizedType) type).getRawType());
        } else if (type instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType) type).getGenericComponentType();
            Class<?> componentClass = getClass(componentType);
            if (componentClass != null) {
                return Array.newInstance(componentClass, 0).getClass();
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * Get the actual type arguments a child class has used to extend a generic
     * base class.
     *
     * @param baseClass the base class
     * @param childClass the child class
     * @return a list of the raw classes for the actual type arguments.
     */
    public static <T> List<Class<?>> getTypeArguments(
            Class<T> baseClass, Class<? extends T> childClass)
    {
        Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
        Type type = childClass;
        // start walking up the inheritance hierarchy until we hit baseClass
        while (!getClass(type).equals(baseClass)) {
            if (type instanceof Class) {
                // there is no useful information for us in raw types, so just keep going.
                type = ((Class) type).getGenericSuperclass();
            } else {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                Class<?> rawType = (Class) parameterizedType.getRawType();

                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
                for (int i = 0; i < actualTypeArguments.length; i++) {
                    resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
                }

                if (!rawType.equals(baseClass)) {
                    type = rawType.getGenericSuperclass();
                }
            }
        }

        // finally, for each actual type argument provided to baseClass, determine (if possible)
        // the raw class for that type argument.
        Type[] actualTypeArguments;
        if (type instanceof Class) {
            actualTypeArguments = ((Class) type).getTypeParameters();
        } else {
            actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
        }
        List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
        // resolve types by chasing down type variables.
        for (Type baseType : actualTypeArguments) {
            while (resolvedTypes.containsKey(baseType)) {
                baseType = resolvedTypes.get(baseType);
            }
            typeArgumentsAsClasses.add(getClass(baseType));
        }
        return typeArgumentsAsClasses;
    }
  }

3
实际的运行时类型参数在此代码的哪一行被读取?
伊万·马塔夫吉

这里?Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Ondrej Bozek

9

我认为还有另一种优雅的解决方案。

您想要做的是(安全地)将泛型类型参数的类型从自定义类传递到超类。

如果允许您将类类型视为类上的“元数据”,则建议在运行时使用Java方法对元数据进行编码:注解。

首先按照以下几行定义自定义注释:

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityAnnotation {
    Class entityClass();
}

然后,您必须将注释添加到子类中。

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

然后,您可以使用以下代码获取基类中的类类型:

import org.springframework.core.annotation.AnnotationUtils;
.
.
.

private Class getGenericParameterType() {
    final Class aClass = this.getClass();
    EntityAnnotation ne = 
         AnnotationUtils.findAnnotation(aClass, EntityAnnotation.class);

    return ne.entityClass();
}

这种方法的一些局限性是:

  1. 您可以PassedGenericType在两个地方而不是非DRY中指定一个通用类型()。
  2. 仅当您可以修改具体子类时,才有可能。

是的,它不是DRY,但是比上面建议的扩展方法更干净。我喜欢 谢谢
agodinhost 19'Jan

8

这是我的解决方案:

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

public class GenericClass<T extends String> {

  public static void main(String[] args) {
     for (TypeVariable typeParam : GenericClass.class.getTypeParameters()) {
      System.out.println(typeParam.getName());
      for (Type bound : typeParam.getBounds()) {
         System.out.println(bound);
      }
    }
  }
}

10
这不是这个问题的答案。
亚当·阿罗德

1
我的代码不是该问题的确切解决方案。它返回该类的通用类型参数,但不返回T的实际类型。但是,这对于那些讨厌这个问题并在寻找我的解决方案的人可能会有所帮助。
Matthias M

1
getClass()。getGenericSuperclass()将达到相同的效果。
2014年

5

这是有效的解决方案!!!

@SuppressWarnings("unchecked")
    private Class<T> getGenericTypeClass() {
        try {
            String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
            Class<?> clazz = Class.forName(className);
            return (Class<T>) clazz;
        } catch (Exception e) {
            throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
        }
    } 

注意: 只能用作超类
1。必须使用类型化类(Child extends Generic<Integer>) 进行扩展;
或者

2。必须作为匿名实现(new Generic<Integer>() {};) 创建。


4

你不能 如果将类型T的成员变量添加到类中(甚至不必初始化它),则可以使用它来恢复类型。


2
糟糕,好的。你必须从构造函数初始化它。
andrewmu

4

这是一种方法,我不得不使用一次或两次:

public abstract class GenericClass<T>{
    public abstract Class<T> getMyType();
}

随着

public class SpecificClass extends GenericClass<String>{

    @Override
    public Class<String> getMyType(){
        return String.class;
    }
}

4
从技术上讲这是可行的,但是不能解决一般情况,我认为这就是原始海报的目的。
ggb667 2013年

这不应该像过去那样被否决-原始海报尚未明确。这个答案提供了一种设计模式的工作,很容易实现,只要它是适合做泛型类的抽象。
VirtualMichael 2015年

4

这种出租车的一种简单解决方案如下

public class GenericDemo<T>{
    private T type;

    GenericDemo(T t)
    {
        this.type = t;
    }

    public String getType()
    {
        return this.type.getClass().getName();
    }

    public static void main(String[] args)
    {
        GenericDemo<Integer> obj = new  GenericDemo<Integer>(5);
        System.out.println("Type: "+ obj.getType());
    }
}

3

为了在这里完成一些答案,无论递归的层次如何高,我都必须获取MyGenericClass的ParametrizedType:

private Class<T> getGenericTypeClass() {
        return (Class<T>) (getParametrizedType(getClass())).getActualTypeArguments()[0];
}

private static ParameterizedType getParametrizedType(Class clazz){
    if(clazz.getSuperclass().equals(MyGenericClass.class)){ // check that we are at the top of the hierarchy
        return (ParameterizedType) clazz.getGenericSuperclass();
    } else {
        return getParametrizedType(clazz.getSuperclass());
    }
}

1

这是我的把戏:

public class Main {

    public static void main(String[] args) throws Exception {

        System.out.println(Main.<String> getClazz());

    }

    static <T> Class getClazz(T... param) {

        return param.getClass().getComponentType();
    }

}

1
注意:当是类型变量时,这不起作用T。如果T是类型变量,则varargs将创建擦除数组T。参见例如http://ideone.com/DIPNwd
Radiodef'Apr

1
这将返回“对象”
yahya

可能是你试图回答一些问题,其他🤔

1

万一您使用通用类型存储变量,可以通过添加getClassType方法轻松解决此问题,如下所示:

public class Constant<T> {
  private T value;

  @SuppressWarnings("unchecked")
  public Class<T> getClassType () {
    return ((Class<T>) value.getClass());
  }
}

我稍后使用提供的类对象检查它是否是给定类的实例,如下所示:

Constant<?> constant = ...;
if (constant.getClassType().equals(Integer.class)) {
    Constant<Integer> integerConstant = (Constant<Integer>)constant;
    Integer value = integerConstant.getValue();
    // ...
}

2
不幸的是,这是有问题的。首先,如果valuenull什么呢?第二,如果value是的子类T呢?当应该Constant<Number> c = new Constant<Number>(new Integer(0)); Class<Number> n = c.getClassType();返回Integer.class时返回Number.class。返回会更正确Class<? extends T>Integer.class 是一个, Class<? extends Number>但不是一个Class<Number>
Radiodef

1

这是我的解决方案

public class GenericClass<T>
{
    private Class<T> realType;

    public GenericClass() {
        findTypeArguments(getClass());
    }

    private void findTypeArguments(Type t) {
        if (t instanceof ParameterizedType) {
            Type[] typeArgs = ((ParameterizedType) t).getActualTypeArguments();
            realType = (Class<T>) typeArgs[0];
        } else {
            Class c = (Class) t;
            findTypeArguments(c.getGenericSuperclass());
        }
    }

    public Type getMyType()
    {
        // How do I return the type of T? (your question)
        return realType;
    }
}

无论您的类层次结构具有多少级别,此解决方案仍然有效,例如:

public class FirstLevelChild<T> extends GenericClass<T> {

}

public class SecondLevelChild extends FirstLevelChild<String> {

}

在这种情况下,getMyType()= java.lang.String


这不是返回T的类型。它不是返回T而不是java.lang.String,除了代码未能将Type(类型)隐蔽为Class <T>
Mohy Eldeen

这是我制作的在线样本。单击编译并执行,即可得到结果。 tutorialspoint.com/...
林宇诚

适用于我-WildFly Weld CDI打破了替代方法。
安德烈

我知道了Exception in thread "main" java.lang.NullPointerException at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.<init>(Main.java:43) at Main.main(Main.java:61)

0
public static final Class<?> getGenericArgument(final Class<?> clazz)
{
    return (Class<?>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
}

0

这是我的解决方案。这些示例应对此进行解释。唯一的要求是,子类必须设置通用类型,而不是对象。

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;

public class TypeUtils {

    /*** EXAMPLES ***/

    public static class Class1<A, B, C> {

        public A someA;
        public B someB;
        public C someC;

        public Class<?> getAType() {
            return getTypeParameterType(this.getClass(), Class1.class, 0);
        }

        public Class<?> getCType() {
            return getTypeParameterType(this.getClass(), Class1.class, 2);
        }
    }

    public static class Class2<D, A, B, E, C> extends Class1<A, B, C> {

        public B someB;
        public D someD;
        public E someE;
    }

    public static class Class3<E, C> extends Class2<String, Integer, Double, E, C> {

        public E someE;
    }

    public static class Class4 extends Class3<Boolean, Long> {

    }

    public static void test() throws NoSuchFieldException {

        Class4 class4 = new Class4();
        Class<?> typeA = class4.getAType(); // typeA = Integer
        Class<?> typeC = class4.getCType(); // typeC = Long

        Field fieldSomeA = class4.getClass().getField("someA");
        Class<?> typeSomeA = TypeUtils.getFieldType(class4.getClass(), fieldSomeA); // typeSomeA = Integer

        Field fieldSomeE = class4.getClass().getField("someE");
        Class<?> typeSomeE = TypeUtils.getFieldType(class4.getClass(), fieldSomeE); // typeSomeE = Boolean


    }

    /*** UTILS ***/

    public static Class<?> getTypeVariableType(Class<?> subClass, TypeVariable<?> typeVariable) {
        Map<TypeVariable<?>, Type> subMap = new HashMap<>();
        Class<?> superClass;
        while ((superClass = subClass.getSuperclass()) != null) {

            Map<TypeVariable<?>, Type> superMap = new HashMap<>();
            Type superGeneric = subClass.getGenericSuperclass();
            if (superGeneric instanceof ParameterizedType) {

                TypeVariable<?>[] typeParams = superClass.getTypeParameters();
                Type[] actualTypeArgs = ((ParameterizedType) superGeneric).getActualTypeArguments();

                for (int i = 0; i < typeParams.length; i++) {
                    Type actualType = actualTypeArgs[i];
                    if (actualType instanceof TypeVariable) {
                        actualType = subMap.get(actualType);
                    }
                    if (typeVariable == typeParams[i]) return (Class<?>) actualType;
                    superMap.put(typeParams[i], actualType);
                }
            }
            subClass = superClass;
            subMap = superMap;
        }
        return null;
    }

    public static Class<?> getTypeParameterType(Class<?> subClass, Class<?> superClass, int typeParameterIndex) {
        return TypeUtils.getTypeVariableType(subClass, superClass.getTypeParameters()[typeParameterIndex]);
    }

    public static Class<?> getFieldType(Class<?> clazz, AccessibleObject element) {
        Class<?> type = null;
        Type genericType = null;

        if (element instanceof Field) {
            type = ((Field) element).getType();
            genericType = ((Field) element).getGenericType();
        } else if (element instanceof Method) {
            type = ((Method) element).getReturnType();
            genericType = ((Method) element).getGenericReturnType();
        }

        if (genericType instanceof TypeVariable) {
            Class<?> typeVariableType = TypeUtils.getTypeVariableType(clazz, (TypeVariable) genericType);
            if (typeVariableType != null) {
                type = typeVariableType;
            }
        }

        return type;
    }

}

-1

我所做的与@Moesio Above相同,但在Kotlin中可以这样进行:

class A<T : SomeClass>() {

    var someClassType : T

    init(){
    this.someClassType = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>
    }

}

-4

对某人可能有用。您可以使用java.lang.ref.WeakReference; 这条路:

class SomeClass<N>{
  WeakReference<N> variableToGetTypeFrom;

  N getType(){
    return variableToGetTypeFrom.get();
  }
}

应该如何使用此类?为什么WeakReference呢 请提供答案的一些解释,而不仅仅是一些代码。
Abhijit Sarkar,

因此,如果您有一个SomeClass<MyClass> 实例SomeClass,则可以实例化并调用getType该实例,并将其运行时设为MyClass
TheLetch18年

当然可以,但是为什么WeakReference呢?您所说的与大多数其他答案没有什么不同。
Abhijit Sarkar,

首先,我的方法更短(更少的代码),其次,弱引用不会阻止其引用被定型,并且据我所知,它不使用反射,因此速度很快
TheLetch

这并没有得到任何东西的类型,它返回类型,其中,仅供参考,您可以使用几乎任何类型的包装做的一个对象(AtomicReferenceListSet)。
Frontear's

-5

我发现这是一个简单易懂且易于解释的解决方案

public class GenericClass<T> {

    private Class classForT(T...t) {
        return t.getClass().getComponentType();
    }

    public static void main(String[] args) {
        GenericClass<String> g = new GenericClass<String>();

        System.out.println(g.classForT());
        System.out.println(String.class);
    }
}

解释一下(T...t)。(这就是为什么此代码不起作用的原因。)
Christopher Schneider
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.