【问题标题】:Cannot create a generic array of OuterClass<T>.InnerClass无法创建 Outer Class<TO>.Inner Class 的通用数组
【发布时间】:2014-08-01 19:31:20
【问题描述】:

我有这个代码

public class OuterClass<T> {
    public OuterClass() {
        InnerClass[] array = new InnerClass[4]; // compile-error
    }

    private class InnerClass {

    }
}

由于无法在我创建数组的行中创建 OuterClass.InnerClass 的通用数组而无法编译。

为什么会这样,我该如何修复/解决它?

【问题讨论】:

  • 我很想知道这是如何复制的。链接的问题与此没有直接关系。我不想创建一个通用数组。
  • AyCe,你是对的 - 它与重复的问题无关。我相应地重新打开了您的问题
  • 这个帖子可能也会有帮助:stackoverflow.com/questions/20475142/…

标签: java arrays generics


【解决方案1】:

InnerClass 是一个非静态内部类。 OuterClass 的非静态成员在 OuterClass 的类型参数 T 的范围内。这意味着 InnerClass 是隐式通用的

每次在OuterClass 的实例上下文中,您只写InnerClass,而没有明确限定它,它被隐式视为OuterClass&lt;T&gt;.InnerClass。所以当你写的时候

InnerClass[] array = new InnerClass[4];

编译器将其视为

OuterClass<T>.InnerClass[] array = new OuterClass<T>.InnerClass[4];
//                                                ^
// see? you are using "new" to create an array of a parameterized type

虽然参数物理上不在InnerClass上,但在OuterClass上,它仍然是InnerClass的类型参数,只是写在不同的位置。

您可能知道,Java 中不允许创建参数化类型的数组。就像List&lt;T&gt;[] = new List&lt;T&gt;[4]; 是不允许的一样。

那么创建泛型数组的常用解决方法是什么?您可以创建一个原始类型的数组:

List<T>[] = new List[4]; // legal

或通配符参数化类型:

List<T>[] = (List<T>[])new List<?>[4]; // legal

现在回到内部类的问题。在这种情况下,原始类型是什么?它不是InnerClass,因为正如我们所见,它是用T 隐式参数化的。我们必须明确限定 InnerClass 使用原始OuterClass 来获得原始InnerClass

InnerClass[] = new OuterClass.InnerClass[4]; // legal

交替使用通配符参数化类型(同样,我们必须将通配符放在OuterClass):

InnerClass[] = (InnerClass[])new OuterClass<?>.InnerClass[4]; // legal

【讨论】:

    【解决方案2】:

    解决方法:创建内部类static

    public class OuterClass<T> {
        public OuterClass() {
            InnerClass[] array = new InnerClass[4];
        }
    
        private static class InnerClass {
    
        }
    }
    

    【讨论】:

    • 提防静态。他们无法访问您班级内的任何其他内容。静态类首先被实例化,它们的生命周期是类与对象的生命周期。这意味着实例变量不适用于您的内部类
    • 有很多方法可以解决这个问题。 InnerClass 可以持有 OuterClass 的一个实例,并且可以通过这个实例访问 OuterClass 的非静态成员。
    • 听起来有点循环/过于复杂。我没有标记或任何东西,因为它可以工作。
    • 我知道将内部类设为静态会起作用。你的第二个想法正是我目前的解决方法,似乎效果很好。但是,另一个答案正是我想要的。
    【解决方案3】:

    你有一个参数化问题。泛型现在需要类型,它正在处理什么。整数、双精度、浮点数;等在编译时。该类型会渗透到您封装的类,但不是以指定类型的方式(outerclass.innerclass),这就是出现问题的原因(请参阅 newacct)。

    因此,您需要对 InnerClass 进行参数化,因为它不知道正在处理什么。将课程从外部课程中取出。

    但是,您对内部类的修复是这样的。

     package quicktest;
    
     public class OJust<T>{
          public OJust() {
             InnerClass[] array = new InnerClass[4]; // compile-error
         }
    
         private class InnerClass<T>{
    
         }
    

    }

    【讨论】:

    • 不错!我不知道这个。谢谢你:)
    • 这是个糟糕的主意。内部类仍由外部T 参数化,但现在有一个单独 内部参数T 将其隐藏。
    • 所以它不只是继承为 T 传递的任何内容?
    猜你喜欢
    • 2017-01-31
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多