不是封闭类 Java

Posted

技术标签:

【中文标题】不是封闭类 Java【英文标题】:Is not an enclosing class 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。对于这个问题,嵌套类并不是一个很好的设计。 【参考方案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 设计模式

【讨论】:

以上是关于不是封闭类 Java的主要内容,如果未能解决你的问题,请参考以下文章

不是封闭的类错误Android Studio

广播接收器 - MainActivity 不是封闭类

从扩展类调用异步 - 错误不是封闭类

Day712. 封闭类-Java8后最重要新特性

Activity 不是 Android Studio 中的封闭类

开放/封闭原则是不是说我们不能更改类的接口?