java - 了解 Java 中的类型擦除
问题描述
如果没有类型擦除,如何实现泛型?据我了解,如果我有class Foo<T>
,T
则基本上替换为 ,Object
并且编译器只有元数据可以帮助它转换为正确的参数化类型。
但是,如果实现了具体化,那么这T
将是实际的参数化类型(而不是 Object)......但我不明白编译器如何能够确定是否new T()
是有效的调用(即 T 可能没有无参数构造函数)。
解决方案
特别是在Java中,构造函数不被子类继承,因此只要给定的参数化类型T
不能缩小到特定类型,您就无法运行new T()
,因为Java是静态类型的,无论是否发生物化。但是,实例化 usingnew
只是使用类的一种情况。
实例
对我来说,未擦除的泛型最明显的用途是能够T
在instanceof
表达式中使用:
class Box<T> {
public boolean isInst(Object obj) {
return obj instanceof T;
}
}
还有一个想法是查看是否T
是其他类的超类或子类,或者检查与类的相等性。
静态方法
通过具体化,Java 将能够“正确地”调用static
方法。T
假设我们有以下类:
class Parent {
void doSomething() { System.out.println("Parent"); }
}
class Child extends Parent {
void doSomething() { System.out.println("Child"); }
}
有了这些定义,那么下面的代码......
class Box<T extends Parent> {
void test() { T.doSomething(); }
public static void main(String...args) {
Box<Parent> parentBox = new Box<>();
Box<Child> childBox = new Box<>();
parentBox.test();
childBox.test();
}
}
...应该打印:
Parent
Child
而是打印:
Parent
Parent
这是因为被擦除T
变成了。Parent
遗产
通用继承(听起来很奇怪)可能(可能)存在:
public class GenericType<T> {
public class Inner extends T { }
public static void main(String...args) {
GenericType<MyClass>.Inner obj = new GenericType<MyClass>().new Inner();
System.out.println(obj instanceof MyClass); // Prints true
}
}
推荐阅读
- firebase - 如何使用最新版本从 Firebase 编辑日期和时间选择器 Vuejs Vuetify
- r - 如何在对数似然函数中添加约束?
- redis - Perl6 Redis 在请求输出时卡住
- mysql - 使用比较和喜欢一起从表中获取结果
- python - 无法使用 docker compose 通过不同容器上的 pyscog2 连接到 postgres DB 容器
- python - 在url中输入中文时出现UnicodeEncodeError
- r - 在 menuItem 点击打开模式
- ios - 连接到 tabbarcontroller 时,无法在 swift 4.2 的导航栏上显示 barbutton 项目?
- excel - 检查文件夹是否为空
- php - 如何使用 Instagram Graph API 在网站上获取非商业帐户的 Instagram 提要?