【问题标题】:Getting a Class instance corresponding to a generic type instantiation获取对应于泛型类型实例化的 Class 实例
【发布时间】:2013-09-12 05:38:09
【问题描述】:

我有以下类型:

public class GenericClass<T> {
    public GenericClass(Class<T> cls) {}
}

但是,当 T 本身是一个泛型类时,我似乎无法调用它:

GenericClass<List<String>> g = new GenericClass<>(???);

使用List.class 无法编译,List&lt;String&gt;.class 是无效语法。如何获取Class&lt;List&lt;String&gt;&gt; 的实例以传递给构造函数?

【问题讨论】:

标签: java generics java-7 type-erasure


【解决方案1】:

这是一个更简单的解决方案.. 它完全隐藏了丑陋。这里的方法是隐式绑定结果类型——并将其与传入的原始类分开。

public class GenericClass<T> {
    public GenericClass(Class<T> cls) {}

    // static constructor;
    //    - hides unchecked ugliness, & implicitly binds 'nicely typed' to result.
    //
    public static <T>  GenericClass<T> create (Class<? super T> clazz) {
        // ugly cast is hidden in here;  no type checking.
        Class<T> clazz_ = (Class<T>)(Class) clazz;
        return new GenericClass( clazz_);
    }
}

用法:

GenericClass<List<String>> g = GenericClass.create( List.class);

我现在将“传入的类”clazz 定义为? super T,但是——如果这太严格了——你可以放宽边界并将参数设为Class&lt;?&gt; clazz

这个解决方案已经在我的 IDE 中进行了测试(至少很快)并且看起来运行良好。我不确定从长远来看,这是否是解决您遇到的任何设计问题的最佳方法 - 但它绝对是解决您当前问题的最简洁的方法。

【讨论】:

  • 看起来没有办法在不产生未经检查的异常的情况下做到这一点...... :(
  • 但这一点都不安全。我可以将Object.class 传递给class 传递给任何T
  • 完全安全.. 当您实际使用生成的实例/创建的对象时。此时,Java 隐式地将泛型转换为实际类型,此时会发生类型检查。 实际类型(不是泛型)的类型安全性始终保留在 JVM 中。这只是一种使原本丑陋的语法变甜的方法。
  • “未经检查的泛型类型操作”/“原始类型”警告可以针对此特定方法抑制。我在我的 IDE 中默认将它们关闭,因为这些警告几乎总是完全虚假的,并且大量由 1.5 之前的代码和非泛化代码引起。
【解决方案2】:

怎么样

GenericClass<List<String>> g =
    new GenericClass<>((Class<List<String>>)(Class<?>)ArrayList.class);

【讨论】:

    【解决方案3】:

    您也可以尝试如下声明构造函数

    public <E extends T> GenericClass(Class<E> cls)
    

    然后您可以通过构造函数传递 List.class 和 List 的任何子级。

    【讨论】:

      猜你喜欢
      • 2013-10-03
      • 2011-04-02
      • 2019-01-20
      • 2016-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多