【问题标题】:Is not an enclosing class Java不是封闭类 Java
【发布时间】:2013-12-13 16:48:36
【问题描述】:

我正在尝试制作俄罗斯方块游戏,但出现编译器错误

Shape is not an enclosing class

当我尝试创建一个对象时

public class Test {
    public static void main(String[] args) {
        Shape s = new Shapes.ZShape();
    }
}

我正在为每个形状使用内部类。这是我的部分代码

public class Shapes {
    class AShape {
    }
    class ZShape {
    }
}

我做错了什么?

【问题讨论】:

  • new Shape().new ZShape();ZShape 类需要一个封闭的实例来实例化。
  • 将内部类移动到单独的文件中
  • @Dimmduh 评论应该是这种情况下的答案。它们不应该是内部类。移动它们将确定存在的 Shape 类的其他问题。
  • 这里不回答这个问题,但我可以建议在AShapeZShape 扩展基类Shapes 的地方使用inheritance。对于这个问题,嵌套类并不是一个很好的设计。

标签: java inner-classes


【解决方案1】:

ZShape 不是静态的,因此它需要外部类的实例。

如果可以的话,最简单的解决方案是制作 ZShape 和任何嵌套类 static

我也可以创建任何字段 finalstatic final

【讨论】:

  • 制作ZShape static 完全违背了他试图做的事情的目的,即实例化ZShape 的副本。
  • @Cardano 让 static 变得更容易,而不是更难。
  • 另一个简单的解决方案是让封闭类实例化内部类,即以这种方式获取 ZShape:ZShape myShape = new Shape().instantiateZShape();。这意味着如果没有 Shape,您获得的 ZShape 就不存在,这就是这里的意图。
  • @Peter Lawrey 您是如何意识到所有 Shape 实例都必须使用相同的 ZShape 的?我不是从他的消息来源那里得到的。
  • 如果我们想要静态或实例,有两种情况。将其设为静态并不总是有帮助。
【解决方案2】:

假设 RetailerProfileModel 是您的 Main 类,RetailerPaymentModel 是其中的一个内部类。可以在类外创建Inner类的对象,如下:

RetailerProfileModel.RetailerPaymentModel paymentModel
        = new RetailerProfileModel().new RetailerPaymentModel();

【讨论】:

  • 这个答案真的很有帮助,我从来不知道你可以连续调用 new 两次(而且我已经做了 8 年以上的 java!)
  • 您当然可以多次调用 new 运算符,直到您不想保留对该对象的引用。
  • 如果内部类的对象是这样创建的,它如何访问外部类的成员?
  • 在内部类本身中,您可以使用 OuterClass.this。我认为没有办法从内部类的代码外部获取实例。当然,你总是可以引入自己的属性: public OuterClass getOuter() { return OuterClass.this; }
  • 虽然这个语法很复杂,让我很难过,但这应该是公认的答案。
【解决方案3】:

我建议不要将非静态类转换为静态类,因为在这种情况下,您的内部类无法访问外部类的非静态成员。

例子:

class Outer
{
    class Inner
    {
        //...
    }
}

因此,在这种情况下,您可以执行以下操作:

Outer o = new Outer();
Outer.Inner obj = o.new Inner();

【讨论】:

  • 那么Outer.Inner obj = (new Outer).new Inner();
  • @HussainKMRBehestee,不,这肯定行不通。但是,这会工作Outer.Inner obj = new Outer().new Inner();
  • 但是阿米特,它对我有用。如果你能解释为什么它不应该工作,我会很高兴。
  • @HussainKMRBehestee,解释:我只能猜测Java中的语法说要实例化一个类,我们需要调用构造函数,而调用构造函数()是强制性的。但是,C、C++ 不是必须的。 Here 是一个不起作用的例子。此外,我发现了这个post。这解释了更多关于 Java 中的语法以及它们是如何被解析的。当这种语法对您有用时,我很乐意看到一个示例案例。
  • 哦,我的错,这是一个错字,Outer.Inner obj = (new Outer()).new Inner();希望这次没问题,感谢您注意到这一点。
【解决方案4】:

docs中所述:

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • 谢谢!刚刚开始。
【解决方案5】:

有时,我们需要创建一个不能是静态的内部类的新实例,因为它依赖于父类的一些全局变量。在这种情况下,如果您尝试创建非静态内部类的实例,则会引发 not an enclosing class 错误。

以问题为例,如果ZShape 不能是静态的,因为它需要Shape 类的全局变量怎么办?

如何创建ZShape 的新实例?方法如下:

在父类中添加getter:

public ZShape getNewZShape() {
    return new ZShape();
}

像这样访问它:

Shape ss = new Shape();
ZShape s = ss.getNewZShape();

【讨论】:

    【解决方案6】:
    Shape shape = new Shape();
    Shape.ZShape zshape = shape.new ZShape();
    

    【讨论】:

      【解决方案7】:

      我也遇到了同样的问题。 我通过为每个内部公共类创建一个实例来解决。 至于你的情况,我建议你使用内部类以外的继承。

      public class Shape {
      
          private String shape;
      
          public ZShape zShpae;
          public SShape sShape;
      
          public Shape(){
            int[][] coords =  noShapeCoords;
            shape = "NoShape";
            zShape = new ZShape();
            sShape = new SShape();
          }
      
          class ZShape{
            int[][] coords =  zShapeCoords;
            String shape = "ZShape";
          }
      
          class SShape{
            int[][] coords = sShapeCoords;
            String shape = "SShape";
          }
      
       //etc
      }
      

      然后你可以 new Shape(); 并通过shape.zShape访问ZShape;

      【讨论】:

      • 一个错误的解决方案。逻辑错误。如果内部类(例如 ZShape)需要设置任何字段,则必须在外部类的构造函数中获取它! public Shape(String field1_innerClass, int field2_innerClass...){zShape = new ZShape(String field1_innerClass, int field2_innerClass...)...}}
      【解决方案8】:

      不需要将嵌套类设为静态,但必须是公共的

      public class Test {
          public static void main(String[] args) {
              Shape shape = new Shape();
              Shape s = shape.new Shape.ZShape();
          }
      }
      

      【讨论】:

        【解决方案9】:

        在阅读接受的答案时,我起初没有意识到的一件事是,将内部类设为静态基本上与将其移动到自己的单独类中相同。

        因此,当得到错误时

        xxx 不是封闭类

        您可以通过以下任一方式解决:

        • static关键字添加到内部类,或者
        • 将其移到自己的单独类中。

        【讨论】:

          【解决方案10】:

          如果父类是单例,请使用以下方式:

          Parent.Child childObject = (Parent.getInstance()).new Child();
          

          getInstance() 将返回父类单例对象。

          【讨论】:

            【解决方案11】:

            为了达到问题的要求,我们可以将类放入接口中:

            public interface Shapes {
                class AShape{
                }
                class ZShape{
                }
            }
            

            然后像作者之前尝试过的那样使用:

            public class Test {
                public static void main(String[] args) {
                    Shape s = new Shapes.ZShape();
                }
            }
            

            如果我们寻找合适的“逻辑”解决方案,应该使用fabric 设计模式

            【讨论】:

              猜你喜欢
              • 2016-05-14
              • 1970-01-01
              • 2020-05-06
              • 2011-07-05
              • 2016-04-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-05-31
              相关资源
              最近更新 更多