【问题标题】:Constructor with generic class is undefined具有泛型类的构造函数未定义
【发布时间】:2012-12-16 23:38:58
【问题描述】:

我遇到了一个我不明白的愚蠢问题。

class Foo<T extends Collection<E>, E> {
  private Class<T> collectionClass;
  private Class<E> elementClass;

  public Foo(Class<T> collectionClass, Class<E> elementClass) {
       this.collectionClass = collectionClass;
       this.elementClass = elementClass;
  }
} 

当我尝试运行它时

Foo<Collection<String>, String> foo = 
    new Foo<Collection<String>, String>(
        Collection.class,
        String.class);

我得到一个编译器错误

java.lang.Error: Unresolved compilation problem: 
The constructor Foo<Collection<String>,String>(Class<Collection>, Class<String>) is undefined

为什么?如果我删除泛型,没关系

Foo foo = 
    new Foo(
        Collection.class,
        String.class);

如果有人有想法,那就太好了,不会让我把头撞到墙上。

【问题讨论】:

    标签: java generics reflection type-erasure


    【解决方案1】:

    没有Collection&lt;String&gt;.class 这样的东西,是问题所在。您的选择包括

    • 不要使用反射;为什么要使用反射?
    • 接受不安全演员表的需要
    • 使用各种工具之一在运行时引用泛型类型,例如 Guava 的 TypeToken

    【讨论】:

    • 最后我重构了我的 API 以避免这种需要。谢谢。
    【解决方案2】:

    您对此无能为力。随便投吧

    new Foo<Collection<String>, String>(
        (Class<Collection<String>>)(Class<?>)Collection.class,
        String.class);
    

    【讨论】:

      【解决方案3】:

      不走运,因为类型擦除,请参阅this question

      但是,可以使用原始集合类和元素类来生成类型安全的Collection&lt;String&gt; 对象。所以去掉Collection中E的冗余,作为Collection。

      【讨论】:

        【解决方案4】:

        对于您的用例,您可能可以放宽构造函数参数类型

        public Foo(Class<?> collectionClass, Class<E> elementClass) 
        {
            this.collectionClass = (Class<T>)collectionClass;
            this.elementClass = elementClass;
        }
        
        Foo<Collection<String>, String> foo = new Foo<>(Collection.class, String.class);
        

        类型检查较少,因此用户必须确保没有传入错误的类,例如

        Foo<Set<String>, String> foo = new Foo<>(List.class, String.class);
            ^^^                                  ^^^^
        

        【讨论】:

        • 希望取消选中强制转换的危险得到控制,因为错误的代码太明显了。
        • 在合理的概率范围内,错误代码显而易见的上下文很小。
        • 对于这个构造函数来说似乎很好;错误的用法显然是错误的。
        【解决方案5】:

        好的,

        我看过其他人的答案,但不是最好的......

        在 Oreilly Tiger 的书(第 5 版)(p167) 中,他们非常明确地声明构造函数 不能 在其签名中包含通配符...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多