【问题标题】:Struggling with generics and classes与泛型和类作斗争
【发布时间】:2009-07-09 06:55:03
【问题描述】:

我一直在为泛型而苦苦挣扎。我不知道为什么这让我发疯。我有一个老问题,我遇到过好几次了。

class Father {
    ...
}

class Child1 extends Father {
    ...
}

class Child2 extends Father {
    ...
}

public class TestClass {
    private static Class<? extends Father>[] myNiceClasses = new Class<? extends Father>[] {
        Child1.class,
        Child2.class
    }
}

不起作用。编译器这样抱怨:

Cannot create a generic array of Class<? extends Father>

如果我将(错误的)数组行更改为

private static Class<Father>[] myNiceClasses = new Class<Father>[] {

出现同样的错误信息,但也添加了这条信息:

Type mismatch: cannot convert from Class<Child1> to Class<Father>

唯一的工作版本是这一行:

private static Class<?>[] myNiceClasses = new Class<?>[] {

这个解决方案并不令人满意,因为你不能那么容易地施法。

所以我的问题是:如何解决这个问题?我脑子里的结在哪里?

【问题讨论】:

    标签: java arrays generics


    【解决方案1】:

    这是因为 java 不支持创建泛型数组。泛型最适用于集合。所以你可以使用 ArrayList 来解决你的问题:

            ArrayList<Class<? extends Father>> myNiceClasses = new ArrayList<Class<? extends Father>>();
            myNiceClasses.add(Child1.class);
            myNiceClasses.add(Child2.class);
    

    【讨论】:

      【解决方案2】:

      quant_dev 的链接线程说的是不能创建泛型数组,因为它们不能保证类型安全。您最终可能会得到泛型不允许的数组中的东西。无论如何,我所知道的最干净的方法是:

      private static Class<? extends Father>[] myNiceClasses =
              (Class<? extends Father>[]) new Class<?>[] {};
      

      【讨论】:

        【解决方案3】:

        【讨论】:

          【解决方案4】:

          泛型和数组是最好避免的组合。编译器不喜欢您创建泛型数组的事实是 Java 泛型是该语言的附加组件这一事实的产物,有时您可以看到连接。另一个例子是异常,你也不能将它们与泛型结合起来。

          我建议在这种情况下避免使用数组。请改用通用列表。

          【讨论】:

            【解决方案5】:

            这是由于所谓的类型擦除。 Java 编译器会在编译过程中擦除所有通用信息。 (这是因为泛型是该语言的后期添加,为了向后兼容,Sun 决定不修改 JVM。这意味着该语言知道泛型,但 JVM 不知道。)

            由于 JVM 在运行时不知道泛型类型,它无法实例化该泛型类型的数组。在您的情况下,它可以做的最好的事情是实例化一个原始类型 Class 的数组。

            在这种情况下,最好使用完全支持泛型的集合框架。

            总结一下:泛型和数组不能混用。

            【讨论】:

              【解决方案6】:

              或者,正如 amit.dev 所说,您可能想要使用列表。在这种情况下,假设 myNiceClasses 字段应该是一个常量,您可以使用Collections.unmodifiableList 确保列表不能更改:

              private static final List<? extends Father> myNiceClasses;
              static {
                  ArrayList<? extends Father> l = new ArrayList<? extends Father>();
                  l.add(Child1.class);
                  l.add(Child2.class);
                  myNiceClasses = Collections.unmodifiableList(l);
              }
              

              它相当冗长,但具有完全不变的优点,因此更容易推理。

              【讨论】:

                猜你喜欢
                • 2011-01-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-02-22
                • 2012-12-12
                • 2020-03-28
                • 1970-01-01
                • 2022-01-08
                相关资源
                最近更新 更多