411

I'm trying to make a Tetris game and I'm getting the compiler error when I try to create an object

Shape is not an enclosing class

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

I'm using inner classes for each shape. Here's part of my code

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

What am I doing wrong?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
V Sebi
  • 4,253
  • 2
  • 15
  • 8

12 Answers12

527

ZShape is not static so it requires an instance of the outer class.

The simplest solution is to make ZShape and any nested class static if you can.

I would also make any fields final or static final that you can as well.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 16
    Making `ZShape` `static` totally defeats the purpose of what he's trying to do, which is instantiate a copy of `ZShape`. – Cardano Feb 15 '14 at 01:58
  • 18
    @Cardano making it `static` makes it easier, not harder. – Peter Lawrey Feb 15 '14 at 12:35
  • 13
    another simple solution is to make the enclosing class instantiate the inner class, i.e. getting ZShape this way: `ZShape myShape = new Shape().instantiateZShape();`. It implies the ZShape you get does not exist without a Shape, which is the intent here. – Vince Nov 10 '14 at 03:41
  • @Peter Lawrey How did you realize that all Shape instances have to use the same ZShape? I don't get it from his source. – The incredible Jan Jun 28 '17 at 11:27
  • @TheincredibleJan There is only one object created so I know they are all that object. – Peter Lawrey Jun 28 '17 at 14:55
  • 2
    There are 2 cases if we want static or an instance. Making it Static will not help always. – Yogesh Chuahan Apr 17 '18 at 07:08
  • @YogeshChuahan if it still compiles after adding `static` to a class, it is probably the right thing to do. – Peter Lawrey Apr 17 '18 at 07:36
  • Your answer is correct and in this case it makes sense to declare them static. I am talking about the other case when we need different values for instances of the class. @PeterLawrey – Yogesh Chuahan Apr 17 '18 at 10:46
  • 2
    The comments here seem to suggest that people don't understand what static nested classes are in Java. Making the class static does not mean that there will only be one instance, it just means that `ZShape` will not need an instance of `Shapes` to exist. – Mark Rotteveel Apr 08 '23 at 14:34
223

Suppose RetailerProfileModel is your Main class and RetailerPaymentModel is an inner class within it. You can create an object of the Inner class outside the class as follows:

RetailerProfileModel.RetailerPaymentModel paymentModel
        = new RetailerProfileModel().new RetailerPaymentModel();
Kartik
  • 7,677
  • 4
  • 28
  • 50
Vishal Kumar
  • 4,419
  • 1
  • 25
  • 31
  • 45
    This answer was really helpful, I never knew you could call new twice in a row (and I've done java for 8+ years!) – PaulBGD Sep 13 '15 at 00:58
  • 1
    You can surely call new operator any number of times until you do not want to keep a reference of that object. – Vishal Kumar Sep 16 '15 at 10:22
  • 1
    If an object of the inner class is create this way, how does it access the members of the outer class? – Alpha Huang Sep 22 '15 at 18:20
  • 1
    Within the inner class itself, you can use OuterClass.this.I don't think there's a way to get the instance from outside the code of the inner class though. Of course, you can always introduce your own property: public OuterClass getOuter() { return OuterClass.this; } – Vishal Kumar Oct 21 '15 at 13:26
  • Works for tests: `underTest = Mockito.mock(Outer.class).new InnerNonStaticClass();` – felvhage Jul 27 '18 at 08:32
  • 3
    While this syntax is pretty convoluted and makes me sad, this should be the accepted answer. – Josh M. Oct 11 '18 at 14:17
  • I have a class i'm using as a storage container for simple class objects (analogous to structs) and this was exactly what I was looking for. Thank you! – Jacob Chesley Feb 24 '19 at 12:33
58

What I would suggest is not converting the non-static class to a static class because in that case, your inner class can't access the non-static members of outer class.

Example :

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

So, in such case, you can do something like:

Outer o = new Outer();
Outer.Inner obj = o.new Inner();
Amit Upadhyay
  • 7,179
  • 4
  • 43
  • 57
  • 1
    What about Outer.Inner obj = (new Outer).new Inner(); – Hussain KMR Behestee Aug 16 '17 at 12:25
  • 1
    @HussainKMRBehestee, no that wouldn't work for sure. However, this would work `Outer.Inner obj = new Outer().new Inner(); ` – Amit Upadhyay Aug 16 '17 at 14:29
  • But Amit, it works for me. I would glad if you could explain why it should not work. – Hussain KMR Behestee Aug 19 '17 at 08:40
  • 1
    @HussainKMRBehestee, explanation: I can only guess that the grammar in Java says that to instantiate a class we need to call the constructor, and while calling the constructor `()` is compulsory. However, C, C++ it's not a must. [Here](https://ideone.com/QgDfMW) is an example which doesn't work. Moreover, I found this [post](https://stackoverflow.com/questions/16513210/calling-a-method-on-a-new-object-in-java-without-parentheses-order-of-operation). which is explaining more about grammar in Java and how they are parsed. I would love to see a sample case when this syntax is working for you. – Amit Upadhyay Aug 19 '17 at 10:53
  • 1
    Oh, my bad, it was a typo, Outer.Inner obj = (new Outer()).new Inner(); hope this time it is ok and thanks for noticing that. – Hussain KMR Behestee Aug 23 '17 at 05:16
21

As stated in the docs:

OuterClass.InnerClass innerObject = outerObject.new InnerClass();
s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
Brennan Miller
  • 219
  • 2
  • 4
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/18470483) – Muhammad Omer Aslam Jan 10 '18 at 01:05
  • Thanks! Just getting started. – Brennan Miller Jan 11 '18 at 01:59
10

Sometimes, we need to create a new instance of an inner class that can't be static because it depends on some global variables of the parent class. In that situation, if you try to create the instance of an inner class that is not static, a not an enclosing class error is thrown.

Taking the example of the question, what if ZShape can't be static because it need global variable of Shape class?

How can you create new instance of ZShape? This is how:

Add a getter in the parent class:

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

Access it like this:

Shape ss = new Shape();
ZShape s = ss.getNewZShape();
David Walschots
  • 12,279
  • 5
  • 36
  • 59
MbPCM
  • 457
  • 5
  • 12
9
Shape shape = new Shape();
Shape.ZShape zshape = shape.new ZShape();
3

In case if Parent class is singleton use following way:

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

where getInstance() will return parent class singleton object.

Neuron
  • 5,141
  • 5
  • 38
  • 59
CoDe
  • 11,056
  • 14
  • 90
  • 197
1

I have encountered the same problem. I solved by creating an instance for every inner public Class. as for you situation, i suggest you use inheritance other than inner classes.

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
}

then you can new Shape(); and visit ZShape through shape.zShape;

  • 1
    A wrong solution. Logical error. If the inner class (e.g. ZShape) requires any field to be set, in the outer class's constructor you must get it! public Shape(String field1_innerClass, int field2_innerClass...){zShape = new ZShape(String field1_innerClass, int field2_innerClass...)...}} – Mohsen Abasi Jun 12 '17 at 06:34
1

No need to make the nested class as static but it must be public

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

One thing I didn't realize at first when reading the accepted answer was that making an inner class static is basically the same thing as moving it to its own separate class.

Thus, when getting the error

xxx is not an enclosing class

You can solve it in either of the following ways:

  • Add the static keyword to the inner class, or
  • Move it out to its own separate class.
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
1

To achieve the requirement from the question, we can put classes into interface:

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

and then use as author tried before:

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

If we looking for the proper "logical" solution, should be used fabric design pattern

Reishin
  • 1,854
  • 18
  • 21
-1

In case that someone has this issue trying to instance a third party component.

In my case was doing a unit test using this component: ChannelSftp.LsEntry

Doing the usual instantiation give me the issue: enter image description here

The workaround was:

    ChannelSftp channelSftp =  new ChannelSftp();
    Constructor<ChannelSftp.LsEntry> constructor = (Constructor<ChannelSftp.LsEntry>) ChannelSftp.LsEntry.class.getDeclaredConstructors()[0];
    constructor.setAccessible(true);
    ChannelSftp.LsEntry lsEntry = constructor.newInstance(channelSftp, "file1.txt", null);

I found original code here

mauronet
  • 850
  • 12
  • 17