我有以下两个课程:
class Generic<T>
{
}
class Foo extends Generic<Student>
{
}
在Generic
内部,我有一个方法需要获取通过T
传递的类的名称
在Java中这可能吗?我知道在C#中,我只会使用typeof
。
我尝试执行以下操作:
String className = new TypeToken<T>() {}.getClass().getName().toString();
但这不提供名称,仅提供Generic$1
答案 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做到这一点。