“好吧,最后——关于仿制药的又一堂小课。”
“现在我要告诉你如何绕过类型擦除。”
“啊。这就是我想知道的事情。”
“您可能已经知道,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,谢谢你给我上了这么有趣的课。”
GO TO FULL VERSION