둘러싼 클래스 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 클래스의 다른 문제를 식별 할 수 있습니다.
예레미야 아담스

여기서 질문에 대답하지는 않지만 여기에서 상속 을 사용 하여 기본 클래스를 확장 AShape하고 ZShape확장하는 것이 좋습니다 Shapes. 중첩 클래스는이 문제에 대한 좋은 디자인이 아닙니다.
Paramvir Singh Karwal

답변:


492

ZShape 정적이 아니므로 외부 클래스의 인스턴스가 필요합니다.

가장 간단한 해결책은 가능한 static경우 ZShape 및 중첩 클래스를 만드는 것 입니다.

나는 또한 어떤 분야를 만들 final거나 static final당신도 할 수 있습니다.


13
만들기는 ZShape static완전히 그 사본의 인스턴스 인 일을하려고 무슨의 목적을 패배 ZShape.
Cardano 2019

17
@Cardano는 어렵지 static않고 더 쉽게 만듭니다.
Peter Lawrey

12
또 다른 간단한 해결책은 엔 클로징 클래스가 내부 클래스를 인스턴스화하는 것입니다. 즉 ZShape를 이런 식으로 가져 오는 것 ZShape myShape = new Shape().instantiateZShape();입니다. 그것은 당신이 얻는 ZShape가 Shape없이 존재하지 않는다는 것을 의미합니다.
빈스

@Peter Lawrey 모든 Shape 인스턴스가 동일한 ZShape를 사용해야한다는 것을 어떻게 알았습니까? 나는 그의 소스에서 그것을 얻지 못한다.
놀라운 1 월

2
정적 또는 인스턴스를 원할 경우 2 가지 경우가 있습니다. 정적으로 만드는 것이 항상 도움이되는 것은 아닙니다.
Yogesh Chuahan

177

RetailerProfileModel이 기본 클래스이고 RetailerPaymentModel이 그 내부 클래스라고 가정하십시오. 다음과 같이 클래스 외부에서 Inner 클래스의 객체를 만들 수 있습니다.

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

34
이 대답은, 당신이 두 번 연속으로 새로운 부를 수있는 정말 도움이 알지도 못하는 한 (내가 8+ 년 완료 자바를했습니다!)
PaulBGD

1
해당 객체에 대한 참조를 유지하지 않을 때까지 새 연산자를 여러 번 호출 할 수 있습니다.
Vishal Kumar

1
내부 클래스의 객체가 이런 식으로 생성되면 외부 클래스의 멤버에 어떻게 액세스합니까?
Xingang Huang

1
내부 클래스 자체에서 OuterClass.this를 사용할 수 있습니다. 내부 클래스의 코드 외부에서 인스턴스를 가져올 수있는 방법이 없다고 생각합니다. 물론 항상 자신의 속성을 소개 할 수 있습니다. public OuterClass getOuter () {return OuterClass.this; }
Vishal Kumar

테스트를 위해 작동 :underTest = Mockito.mock(Outer.class).new InnerNonStaticClass();
felvhage

48

내가 제안하는 것은 비 정적 클래스를 정적 ​​클래스로 변환하지 않는 것입니다.이 경우 내부 클래스는 외부 클래스의 비 정적 멤버에 액세스 할 수 없기 때문입니다.

예 :

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

따라서 이러한 경우 다음과 같은 작업을 수행 할 수 있습니다.

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

Outer.Inner는 어떻습니까 obj = (new Outer) .new Inner ();
Hussain KMR Behestee

1
@HussainKMRBehestee, 그건 확실하지 않습니다. 그러나 이것은 작동합니다Outer.Inner obj = new Outer().new Inner();
Amit Upadhyay

그러나 Amit, 그것은 나를 위해 일합니다. 왜 작동하지 않아야하는지 설명해 주시면 기쁩니다.
Hussain KMR Behestee

1
@HussainKMRBehestee, 설명 : Java의 문법에 따르면 클래스를 인스턴스화하려면 생성자를 호출해야하며 생성자를 호출하는 ()것은 필수 라고 말합니다 . 그러나 C, C ++는 필수는 아닙니다. 작동하지 않는 예는 다음과 같습니다 . 또한이 게시물을 찾았 습니다 . Java 문법과 구문 분석 방법에 대해 자세히 설명합니다. 이 구문이 효과가있을 때 샘플 사례를보고 싶습니다.
Upadhyay

1
오, 내 나쁜, 오타였습니다. Outer.Inner obj = (new Outer ()). new Inner (); 이번에는 그것이 좋았고 그것을 알아 주셔서 감사합니다.
Hussain KMR Behestee

18

문서에 명시된 바와 같이 :

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

이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다. - 리뷰에서
Muhammad Omer Aslam

감사! 그냥 시작해
Brennan Miller

10

때로는 부모 클래스의 전역 변수에 의존하기 때문에 정적 일 수없는 내부 클래스의 새 인스턴스를 만들어야 할 때가 있습니다. 이 상황에서 정적이 아닌 내부 클래스의 인스턴스를 작성하려고하면 not an enclosing class오류가 발생합니다.

질문의 예를 들어, 클래스의 ZShape전역 변수가 필요하기 때문에 정적 일 수 없다면 Shape어떻게됩니까?

새 인스턴스를 ZShape어떻게 만들 수 있습니까? 방법은 다음과 같습니다.

부모 클래스에서 getter를 추가하십시오.

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)에 필드를 설정해야하는 경우 외부 클래스의 생성자에서 가져와야합니다! 공공 모양 (문자열 field1_innerClass, field2_innerClass ... INT) {zShape = 새로운 ZShape (field2_innerClass INT 문자열 field1_innerClass, ...) ...}}
모흐센 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.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디자인 패턴을 사용해야합니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.