不是封闭的类Java


366

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

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 {
    }
}

我究竟做错了什么 ?


160
new Shape().new ZShape();。该类ZShape需要实例化一个封闭的实例。
Sotirios Delimanolis

4
将内部类移动到单独的文件中
Dimmduh

在这种情况下,@ Dimmduh评论应为答案。它们不应该是内部类。移动它们将确定Shape类存在的其他问题。
耶利米亚当斯

在这里不回答问题,但是我可以建议在此处使用继承AShapeZShape扩展基类Shapes。嵌套类并不是解决此问题的好方法。
Paramvir Singh Karwal,

Answers:


492

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

最简单的解决方案是使ZShape和任何嵌套类 static如果可以的话)。

我也将填写任何字段,final或者static final也可以。


13
制作ZShape static完全违背了什么他要做的,这是实例化副本的目的ZShape
卡尔达诺2014年

17
@Cardano使它static变得更容易,而不是更难。
彼得·劳瑞

12
另一个简单的办法是使封闭类实例化内部类,即获得ZShape这样:ZShape myShape = new Shape().instantiateZShape();。这意味着获得的ZShape不没有Shape就不存在,这就是这里的意图。
文斯2014年

@Peter Lawrey您如何意识到所有Shape实例都必须使用相同的ZShape?我从他那儿得不到信息。
令人难以置信的

2
如果需要静态或实例,有两种情况。将其设置为静态将永远不会有帮助。
Yogesh Chuahan

177

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

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

34
这个答案非常有帮助,我不知道您可以连续两次调用new(并且我已经使用Java已有8年以上了!)
PaulBGD 2015年

1
您当然可以多次调用new运算符,直到您不想保留该对象的引用为止。
Vishal Kumar

1
如果内部类的对象是以这种方式创建的,那么它如何访问外部类的成员?
黄心刚

1
在内部类内部,可以使用OuterClass.this。我认为没有办法从内部类的代码外部获取实例。当然,您总是可以引入自己的属性:public OuterClass getOuter(){return OuterClass.this; }
Vishal Kumar

测试作品:underTest = Mockito.mock(Outer.class).new InnerNonStaticClass();
felvhage '18

48

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

范例:

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

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

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

那么Outer.Inner obj =(new Outer).new Inner();
侯赛因KMR Behestee

1
@HussainKMRBehestee,不,那肯定不会起作用。但是,这可以正常工作Outer.Inner obj = new Outer().new Inner();
Amit Upadhyay

但是阿米特,对我有用。如果您能解释为什么它不起作用,我将非常高兴。
侯赛因KMR Behestee

1
@HussainKMRBehestee,解释:我只能猜测Java的语法说要实例化一个类,我们需要调用构造函数,而调用构造函数()是强制性的。但是,C,C ++不是必须的。是一个不起作用的示例。此外,我发现了这篇文章。它将解释有关Java语法及其语法的更多信息。当这种语法为您服务时,我很想看看一个示例案例。
阿米特·阿帕德哈伊

1
哦,我不好,这是一个错字,Outer.Inner obj =(new Outer())。new Inner(); 希望这次没事,感谢您的注意。
侯赛因KMR Behestee


10

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

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

如何创建的新实例ZShape?这是这样的:

在父类中添加吸气剂:

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

像这样访问它:

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


1

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

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
}

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


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

1

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

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

1

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

因此,当出现错误时

xxx不是封闭的类

您可以通过以下两种方式解决此问题:

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

1

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

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

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


0

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

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

然后使用以前尝试过的作者身份:

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.