扩展类型参数的内联 class
Inline class which extends a type parameter
我想写一个快速而肮脏的帮助程序 class 可以快速保存我的对象。因此我正在使用 OrmLite。
我不想在我的 classes 上添加注释,所以我尝试在没有任何字节码库的情况下即时添加包装器。
<T> void save(T o) {
@DatabaseTable
class wrap extends T {
@DatabaseField(generatedId = true)
public Long id;
}
try {
Dao<T, Long> d = (Dao<T, Long>) getClassDao(o.getClass());
TableUtils.createTableIfNotExists(connectionSource, o.getClass());
d.createOrUpdate(o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
问题是 class wrap extends T
- 为什么无法扩展 T
?
因为 T 可能是最终的。最终类无法延期。
至少这是禁止扩展泛型类型的合乎逻辑的原因。其他答案中解释了技术背景。
这是一个奇怪但有趣的问题!给出一个准确而详尽的答案是很棘手的。可能有很多不同的原因,但我认为以下一个是最重要的:
编译器只会生成一个版本的 save
。 要使 class wrap extends T
起作用,参数 T
必须对于不同类型的 save
每次使用都是不同的具体 classes,但这不是泛型的工作方式。 save
只编译一次,save
里面 T
是类型参数,不是具体类型。 (这与类型擦除有些相关,但又有所不同,见下文。)
另一个原因是type erasure。 Java 中的通用类型仅存在于 编译时 。另一方面,Java 中的 class 具有运行时表示(例如,与 C++ 形成对比)。因此,class 的运行时表示不可能从泛型类型的仅编译时构造生成。
<T>
是泛型,不是真正的class。泛型是一个编译时概念,它在运行时被擦除,而 class 是一个运行时的东西,它确实有相应的字节码。您不能声明泛型 <T>
的子 class 因为编译器不知道那个超级 class 是什么
我想写一个快速而肮脏的帮助程序 class 可以快速保存我的对象。因此我正在使用 OrmLite。
我不想在我的 classes 上添加注释,所以我尝试在没有任何字节码库的情况下即时添加包装器。
<T> void save(T o) {
@DatabaseTable
class wrap extends T {
@DatabaseField(generatedId = true)
public Long id;
}
try {
Dao<T, Long> d = (Dao<T, Long>) getClassDao(o.getClass());
TableUtils.createTableIfNotExists(connectionSource, o.getClass());
d.createOrUpdate(o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
问题是 class wrap extends T
- 为什么无法扩展 T
?
因为 T 可能是最终的。最终类无法延期。
至少这是禁止扩展泛型类型的合乎逻辑的原因。其他答案中解释了技术背景。
这是一个奇怪但有趣的问题!给出一个准确而详尽的答案是很棘手的。可能有很多不同的原因,但我认为以下一个是最重要的:
编译器只会生成一个版本的 save
。 要使 class wrap extends T
起作用,参数 T
必须对于不同类型的 save
每次使用都是不同的具体 classes,但这不是泛型的工作方式。 save
只编译一次,save
里面 T
是类型参数,不是具体类型。 (这与类型擦除有些相关,但又有所不同,见下文。)
另一个原因是type erasure。 Java 中的通用类型仅存在于 编译时 。另一方面,Java 中的 class 具有运行时表示(例如,与 C++ 形成对比)。因此,class 的运行时表示不可能从泛型类型的仅编译时构造生成。
<T>
是泛型,不是真正的class。泛型是一个编译时概念,它在运行时被擦除,而 class 是一个运行时的东西,它确实有相应的字节码。您不能声明泛型 <T>
的子 class 因为编译器不知道那个超级 class 是什么