例子均来自 java 编程思想:
//: generics/ArrayMaker.java
import java.lang.reflect.*;
import java.util.*;
public class ArrayMaker<T> {
private Class<T> kind;
public ArrayMaker(Class<T> kind) { this.kind = kind; }
@SuppressWarnings("unchecked")
T[] create(int size) {
return (T[])Array.newInstance(kind, size);
}
public static void main(String[] args) {
ArrayMaker<String> stringMaker =
new ArrayMaker<String>(String.class);
String[] stringArray = stringMaker.create(9);
System.out.println(Arrays.toString(stringArray));
}
} /* Output:
[null, null, null, null, null, null, null, null, null]
*///:~
作者刚在这个例子下说:即使 kind 被存储成了 Class<t>,擦除也意味着它实际上将存储为 Class,没有任何参数。Array.newInstance 传递过去的参数实际并未拥有 kind 所蕴含的类型信息。 我觉得作者说的有道理,确实 Class<t>的 T 作为类型参数不会被实际存储,但看完我有点担心对 Class 对象的使用了,因为 Class 对象并没有存储实际类型。我甚至开始怀疑以前 Class 对象的用法,它都没有存储实际类型,那它到底是怎么 newInstance 的呢?怎么还能产生正确的结果呢?</t></t>
//: generics/ClassTypeCapture.java
class Building {}
class House extends Building {}
public class ClassTypeCapture<T> {
Class<T> kind;
public ClassTypeCapture(Class<T> kind) {
this.kind = kind;
}
public boolean f(Object arg) {
return kind.isInstance(arg);
}
public static void main(String[] args) {
ClassTypeCapture<Building> ctt1 =
new ClassTypeCapture<Building>(Building.class);
System.out.println(ctt1.f(new Building()));
System.out.println(ctt1.f(new House()));
ClassTypeCapture<House> ctt2 =
new ClassTypeCapture<House>(House.class);
System.out.println(ctt2.f(new Building()));
System.out.println(ctt2.f(new House()));
}
} /* Output:
true
true
false
true
*///:~
这里作者说:如果引入类型标签,就可以转而使用动态的 isInstance 了。总之他意思是用 Class 对象可以对擦除进行补偿。
但这个例子中居然可以使用 Class 对象的 isInstance 方法,而且可以正确的返回值。那他前面强调的“即使 kind 被存储成了 Class<t>,擦除也意味着它实际上将存储为 Class”的这个担心点也不复存在了吗?</t>
总之,问题就是:1 是否 Class 对象不会存储实际类型呢? 2 如果 Class 对象没有存储实际类型,那它到底是怎么正确工作的呢?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.