Java:如何从泛型类型获取类文本?
通常,我看到人们使用类文字如下:Java:如何从泛型类型获取类文本?,java,generics,class,literals,Java,Generics,Class,Literals,通常,我看到人们使用类文字如下: Class<Foo> cls = Foo.class; Class cls=Foo.Class; 但是如果类型是泛型的,例如列表,该怎么办?这工作正常,但有一个警告,因为列表应该参数化: Class<List> cls = List.class Class cls=List.Class 那么为什么不添加一个?这会导致类型不匹配错误: Class<List<?>> cls = List.class Clas
Class<Foo> cls = Foo.class;
Class cls=Foo.Class;
但是如果类型是泛型的,例如列表,该怎么办?这工作正常,但有一个警告,因为列表应该参数化:
Class<List> cls = List.class
Class cls=List.Class
那么为什么不添加一个
?这会导致类型不匹配错误:
Class<List<?>> cls = List.class
Class你不能因为
Java泛型只不过是对象强制转换的语法糖。证明:
List<Integer> list1 = new ArrayList<Integer>();
List<String> list2 = (List<String>)list1;
list2.add("foo"); // perfectly legal
重要的部分是类
换句话说,从以下方面:
为什么具体的参数化类型没有类文字?
因为参数化类型没有精确的运行时类型表示。
类文字表示类
表示给定类型的。
例如,类literal
String.class
表示class
对象,该对象表示该类型
字符串
与
类
在
方法getClass
在
String
对象。类文本可以
用于运行时类型检查和
供思考
参数化类型将丢失其类型
将参数转换为时的参数
编译过程中的字节码
这个过程称为类型擦除。作为一个
类型擦除的副作用,所有
泛型类型共享的实例化
相同的运行时表示,
即对应的原始
类型。换句话说,参数化
类型没有类型表示
他们自己的。因此,有
形成类文本没有意义
例如List.class
,
List.class
和List.class
,因为不存在此类类
对象。
只有原始类型列表
具有类
表示其运行时的
类型。它被称为
List.class
你不能因为这个原因
Java泛型只不过是对象强制转换的语法糖。证明:
List<Integer> list1 = new ArrayList<Integer>();
List<String> list2 = (List<String>)list1;
list2.add("foo"); // perfectly legal
重要的部分是类
换句话说,从以下方面:
为什么具体的参数化类型没有类文字?
因为参数化类型没有精确的运行时类型表示。
类文字表示类
表示给定类型的。
例如,类literal
String.class
表示class
对象,该对象表示该类型
字符串
与
类
在
方法getClass
在
String
对象。类文本可以
用于运行时类型检查和
供思考
参数化类型将丢失其类型
将参数转换为时的参数
编译过程中的字节码
这个过程称为类型擦除。作为一个
类型擦除的副作用,所有
泛型类型共享的实例化
相同的运行时表示,
即对应的原始
类型。换句话说,参数化
类型没有类型表示
他们自己的。因此,有
形成类文本没有意义
例如List.class
,
List.class
和List.class
,因为不存在此类类
对象。
只有原始类型列表
具有类
表示其运行时的
类型。它被称为
List.class
为了解释克莱特斯的答案,在运行时删除了所有泛型类型的记录。泛型仅在编译器中处理,用于提供额外的类型安全性。它们实际上只是一种简写,允许编译器在适当的位置插入类型转换。例如,以前您必须执行以下操作:
List x = new ArrayList();
x.add(new SomeClass());
Iterator i = x.iterator();
SomeClass z = (SomeClass) i.next();
变成
List<SomeClass> x = new ArrayList<SomeClass>();
x.add(new SomeClass());
Iterator<SomeClass> i = x.iterator();
SomeClass z = i.next();
List x=new ArrayList();
x、 添加(newsomeclass());
迭代器i=x.Iterator();
SomeClass z=i.next();
这允许编译器在编译时检查您的代码,但在运行时它看起来仍然像第一个示例。为了详细说明cletus的答案,在运行时删除所有泛型类型的记录。泛型仅在编译器中处理,用于提供额外的类型安全性。它们实际上只是一种简写,允许编译器在适当的位置插入类型转换。例如,以前您必须执行以下操作:
List x = new ArrayList();
x.add(new SomeClass());
Iterator i = x.iterator();
SomeClass z = (SomeClass) i.next();
变成
List<SomeClass> x = new ArrayList<SomeClass>();
x.add(new SomeClass());
Iterator<SomeClass> i = x.iterator();
SomeClass z = i.next();
List x=new ArrayList();
x、 添加(newsomeclass());
迭代器i=x.Iterator();
SomeClass z=i.next();
这允许编译器在编译时检查代码,但在运行时它看起来仍然像第一个示例。参数化类型没有类文本,但是存在正确定义这些类型的类型对象
请参见java.lang.reflect.ParameterizedType
-
Google的Gson库定义了一个TypeToken类,该类允许简单地生成参数化类型,并使用它以通用友好的方式为json对象指定复杂的参数化类型。在您的示例中,您将使用:
Type typeOfListOfFoo = new TypeToken<List<Foo>>(){}.getType()
Type-typeOfListOfFoo=new-TypeToken(){}.getType()
我打算发布指向TypeToken和Gson类javadoc的链接,但Stack Overflow不允许我发布多个链接,因为我是一个新用户,您可以使用Google search轻松找到它们。参数化类型没有类文本,但是存在正确定义这些类型的类型对象
请参见java.lang.reflect.ParameterizedType
-
Google的Gson库定义了一个TypeToken类,该类允许简单地生成参数化类型,并使用它以通用友好的方式为json对象指定复杂的参数化类型。在您的示例中,您将使用:
Type typeOfListOfFoo = new TypeToken<List<Foo>>(){}.getType()
Type-typeOfListOfFoo=new-TypeToken(){}.getType()
我打算发帖
static void test1() {
CaptureType<String> t1 = new CaptureType<String>() {
};
equals(t1.getRawType(), String.class);
}
static void test2() {
CaptureType<List<String>> t1 = new CaptureType<List<String>>() {
};
equals(t1.getRawType(), List.class);
equals(t1.getParamADT().getParameters().get(0).getRawType(), String.class);
}
private static void test3() {
CaptureType<List<List<String>>> t1 = new CaptureType<List<List<String>>>() {
};
equals(t1.getParamADT().getRawType(), List.class);
equals(t1.getParamADT().getParameters().get(0).getRawType(), List.class);
}
static class Test4 extends CaptureType<List<String>> {
}
static void test4() {
Test4 test4 = new Test4();
equals(test4.getParamADT().getRawType(), List.class);
}
static class PreTest5<S> extends CaptureType<Integer> {
}
static class Test5 extends PreTest5<Integer> {
}
static void test5() {
Test5 test5 = new Test5();
equals(test5.getTypeParam(), Integer.class);
}
static class PreTest6<S> extends CaptureType<S> {
}
static class Test6 extends PreTest6<Integer> {
}
static void test6() {
Test6 test6 = new Test6();
equals(test6.getTypeParam(), Integer.class);
}
class X<T> extends CaptureType<T> {
}
class Y<A, B> extends X<B> {
}
class Z<Q> extends Y<Q, Map<Integer, List<List<List<Integer>>>>> {
}
void test7(){
Z<String> z = new Z<>();
TypeADT param = z.getParamADT();
equals(param.getRawType(), Map.class);
List<TypeADT> parameters = param.getParameters();
equals(parameters.get(0).getRawType(), Integer.class);
equals(parameters.get(1).getRawType(), List.class);
equals(parameters.get(1).getParameters().get(0).getRawType(), List.class);
equals(parameters.get(1).getParameters().get(0).getParameters().get(0).getRawType(), List.class);
equals(parameters.get(1).getParameters().get(0).getParameters().get(0).getParameters().get(0).getRawType(), Integer.class);
}
static void test8() throws IllegalAccessException, InstantiationException {
CaptureType<int[]> type = new CaptureType<int[]>() {
};
equals(type.getRawType(), int[].class);
}
static void test9(){
CaptureType<String[]> type = new CaptureType<String[]>() {
};
equals(type.getRawType(), String[].class);
}
static class SomeClass<T> extends CaptureType<T>{}
static void test10(){
SomeClass<String> claz = new SomeClass<>();
try{
claz.getRawType();
throw new RuntimeException("Shouldnt come here");
}catch (RuntimeException ex){
}
}
static void equals(Object a, Object b) {
if (!a.equals(b)) {
throw new RuntimeException("Test failed. " + a + " != " + b);
}
}
class SomeClass<T> extends CaptureType<T>{}
SomeClass<String> claz = new SomeClass<>();
@SuppressWarnings("unchecked")
private static <T> Class<T> generify(Class<?> cls) {
return (Class<T>)cls;
}
Class<List<Foo>> cls = generify(List.class);
Class<Map<String, Integer>> cls;
cls = generify(Map.class);
cls = TheClass.<Map<String, Integer>>generify(Map.class);
funWithTypeParam(generify(Map.class));
public void funWithTypeParam(Class<Map<String, Integer>> cls) {
}
@SuppressWarnings("unchecked")
Class<List<String>> stringListClass = (Class<List<String>>) (Class<?>) List.class;
List<Integer> intList = new ArrayList<>();
intList.add(1);
List<String> stringList = stringListClass.cast(intList);
// Surprise!
String firstElement = stringList.get(0);