“好吧,最后——关于仿制药的又一堂小课。”

“现在我要告诉你如何绕过类型擦除。”

“啊。这就是我想知道的事情。”

“您可能已经知道,Java 有一个 Class 类型,用于存储对对象类的引用。”以下是一些示例:

例子
Class clazz = Integer.class;
Class clazz = String.class;
Class clazz = "abc".getClass();

“啊。”

“但你可能不知道的是,还有一个泛型类,叫做 Class。而泛型类变量只能存储对由类型参数确定的类型的引用。 下面是一些例子:”

例子
Class<Integer> clazz1 = Integer.class; // Everything works well
Class<String> clazz2 = Integer.class; // Compilation error
Class<String> clazz1 = String.class; // Everything works well
Class<String> clazz2 = int.class; // Compilation error
Class<? extends String> clazz1 = "abc".getClass(); // Everything works well
Class<Object> clazz2 = "abc".getClass(); // Compilation error

“为什么会这样?”

“嗯,Integer 的类字段的值(即 Integer.class)实际上是一个 Class<Integer> 对象。”

“但让我们继续前进吧。”

“利用 Class<T> — 是泛型这一事实,并且这种类型的变量只能保存 T 类型的值,您可以像这样巧妙地将它们组合在一起:”

例子
class Zoo<T>
{
 Class<T> clazz;
 ArrayList<T> animals = new ArrayList<T>

 Zoo(Class<T> clazz)
 {
  this.clazz = clazz;
 }

 public T createNewAnimal()
 {
  T animal = clazz.newInstance();
  animals.add(animal);
  return animal
 }
}
用法
Zoo<Tiger> zoo = new Zoo<Tiger>(Tiger.class); // This is where we pass the type!
Tiger tiger = zoo.createNewAnimal();

“这不是一个非常棘手的操作——我们只是传递对所需类型的引用。但是,如果我们只是使用 Class 而不是 Class<T>,那么有人可能会不小心传递两种不同的类型:一种作为 T 参数,另一个给构造函数。”

“啊。我明白了。没有发生任何超自然现象,但也没有什么可怕的。有一个类型的参考,你可以使用它。它有效,这对我来说已经足够了。”

“这个男孩变成了一个男人!‘这行得通,对我来说已经足够了’通常是最好的选择。”

“现在可以用 Java 重做很多事情,但我们需要保持与旧代码的兼容性。”

“数以万计流行的完善的库是当今 Java 最有力的论据。因此,Java 通过保持向后兼容性仍然是最受欢迎的语言,因此它无法引入根本性的创新。”

“好吧,我要用二十一点构建我自己的 Java,然后……”

“好吧,我今天已经累了。下次再见。”

“再见,Rishi,谢谢你给我上了这么有趣的课。”