扩展类型参数的内联 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 是什么