Java-获取通用类的名称

时间:2019-01-04 18:14:43

标签: java spring

我有以下两个课程:

class Generic<T> 
{

}

class Foo extends Generic<Student>
{

}

Generic内部,我有一个方法需要获取通过T传递的类的名称

在Java中这可能吗?我知道在C#中,我只会使用typeof

我尝试执行以下操作:

String className = new TypeToken<T>() {}.getClass().getName().toString();

但这不提供名称,仅提供Generic$1

4 个答案:

答案 0 :(得分:2)

使用 getGenericSuperclass()方法并检查是否为 ParameterizedType 然后使用getActualTypeArguments()获取所有参数,这些参数返回 Type 数组, 请记住,泛型类可能使用不止一种类型,例如Map(Map

public Class<?> getGenericType(Object obj) {
    Class<?> genericType = null;
    Type gnrcType = obj.getClass().getGenericSuperclass();
    if (gnrcType instanceof ParameterizedType) {
        ParameterizedType parameterizedType = (ParameterizedType) gnrcType;
        Type types[] = parameterizedType.getActualTypeArguments();

        if (types != null && types.length > 0) {
            Type type = types[0];
            if (type instanceof Class) {
                genericType = (Class<?>) type;
            }
        }
    }
    return genericType;
}

答案 1 :(得分:0)

我假设Generic<T>总是用提供类型参数的类作为实际子类,如Foo代码中那样。在那种情况下,类型信息仍然可以使用Class.getGenericSupertype获得。这是一个简单的例子。

import java.lang.reflect.*;

class Generic<T> 
{
    public String name() {
        Class<?> clazz = this.getClass();
        for (;;) {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass == null) {
                throw new IllegalStateException();
            }
            if (superClass == Generic.class) {
                Type genericSuper = clazz.getGenericSuperclass();
                if (genericSuper instanceof ParameterizedType) {
                    ParameterizedType parameterized = (ParameterizedType)genericSuper;
                    Type[] params = parameterized.getActualTypeArguments();
                    if (params.length == 1) {
                        Type param = params[0];
                        if (param instanceof Class<?>) {
                            return ((Class<?>)param).getName();
                        }
                    }
                }
                throw new IllegalStateException();
            }
            clazz = superClass;
        }
    }
}

class Foo extends Generic<Student>
{

}
interface Student {}

interface Code {
   static void main(String[] args) {
       System.err.println(new Foo().name());
   }
}

仅处理简单的案例。例如,如果Foo extends Generic<Set<Student>>T不是Class

答案 2 :(得分:0)

获取通用类名称的简单方法。

定义一个通用类

public class GenericClass<T> {

private final Class<T> type;

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

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

}

将此通用类用作参数

GenericClass type = new GenericClass(MyEntity.class);
exampleMethod(type);

在exampleMethod方法中

public void exampleMethod(GenericClass type) {
    String fullName= type.getType().getCanonicalName(); //"com.example.MyEntity"
    String sortName= type.getType().getSimpleName(); //"MyEntity"
}

答案 3 :(得分:-1)

C#和Java以非常不同的方式实现泛型。

C#在运行时具有真实的泛型和泛型信息。出于向后兼容性的原因,Java使用类型擦除-这是所有通用魔术都在编译器中,并且在各处都用Object代替T,并且在运行时您不知道通用类型。

Java泛型仍然比C ++模板好,后者在编译时也不比宏替换好。但是Java不能做C#样式的泛型而不破坏与较早版本的运行时/字节码的向后兼容性。

总而言之,您无法使用Java做到这一点。