정적 메서드 내에서 비 ​​정적 내부 클래스를 인스턴스화하는 방법은 무엇입니까?


122

다음 코드가 있습니다.

public class MyClass {

   class Inner {
     int s, e, p;
   }

   public static void main(String args[]) {
     Inner in;
   }
}

이 부분까지 코드는 괜찮지 만 in = new Inner()표시되는 것처럼 기본 메서드 내에서 'in'을 인스턴스화 할 수 없습니다 non static field cannot be referenced in static context.

내가 할 수있는 방법은 무엇입니까? 내 Inner클래스를 정적 으로 만들고 싶지 않습니다 .


답변:


201

다른 외부 클래스에 대한 참조도 있어야합니다.

Inner inner = new MyClass().new Inner();

Inner가 정적이라면

Inner inner = new MyClass.Inner();

53
이 대답은 내 인생관을 바꿨습니다. outer.new Inner ()? 가능성도 고려하지 않았습니다. O_O
AlbeyAmakiir

1
정적 내부의 경우 단순히 Inner inner = new Inner () 할 수 없습니까?
Can Lu

1
@CanLu를 사용하여 정적 중첩 클래스에 대한 개체를 만들려면 OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). 중첩 클래스
LittleLittleQ

37

"일반"내부 클래스에는 Outer 클래스 인스턴스에 대한 숨겨진 (암시 적) 포인터가 있습니다. 이를 통해 컴파일러는 포인터를 입력하지 않고도 포인터를 추적하는 코드를 생성 할 수 있습니다. 예를 들어 외부 클래스에 "a"변수가있는 경우 내부 클래스의 코드는 "a = 0"을 수행 할 수 있지만 컴파일러는 숨겨진 포인터를 아래에 유지하면서 "outerPointer.a = 0"에 대한 코드를 생성합니다. 커버.

즉, 내부 클래스의 인스턴스를 만들 때 연결할 외부 클래스의 인스턴스가 있어야합니다. 외부 클래스의 메서드 내에서이 생성을 수행하면 컴파일러는 "this"를 암시 적 포인터로 사용하는 것을 알고 있습니다. 다른 외부 인스턴스에 연결하려면 특별한 "새"구문을 사용합니다 (아래 코드 스 니펫 참조).

내부 클래스를 "정적"으로 만들면 숨겨진 포인터가없고 내부 클래스가 외부 클래스의 멤버를 참조 할 수 없습니다. 정적 내부 클래스는 일반 클래스와 동일하지만 이름은 부모 내부에서 범위가 지정됩니다.

다음은 정적 및 비 정적 내부 클래스를 만드는 구문을 보여주는 코드 스 니펫입니다.

public class MyClass {

    int a,b,c; // Some members for MyClass

    static class InnerOne {
        int s,e,p;
        void clearA() {
            //a = 0;  Can't do this ... no outer pointer
        }
    }

    class InnerTwo {
        //MyClass parentPointer;      Hidden pointer to outer instance
        void clearA() {         
            a = 0;
            //outerPointer.a = 0      The compiler generates this code
        }       
    }

    void myClassMember() {
        // The compiler knows that "this" is the outer reference to give
        // to the new "two" instance.
        InnerTwo two = new InnerTwo(); //same as this.new InnerTwo()
    }

    public static void main(String args[]) {

        MyClass outer = new MyClass();

        InnerTwo x = outer.new InnerTwo(); // Have to set the hidden pointer
        InnerOne y = new InnerOne(); // a "static" inner has no hidden pointer
        InnerOne z = new MyClass.InnerOne(); // In other classes you have to spell out the scope

    }

}

4

new Inner()메서드 내 에서 만들려면 클래스의 인스턴스 메서드에서 수행하십시오 MyClass.

public void main(){
  Inner inner = new Inner();
}

public static void main(String args[]){
  new MyClass().main();
}

0

Alexei Kaigorodov가 정답입니다. 그의 솔루션을 사용하면 동일한 클래스의 main ()과 같은 정적 메서드 내에서 내부 클래스를 인스턴스화 할 수 있습니다. 그렇지 않으면 정적 메서드 내에서 내부 클래스를 인스턴스화 할 수 없습니다. 컴파일되지 않습니다. Alexei의 솔루션은 컴파일을 수행하며 정적 메서드에서 내부 클래스를 인스턴스화 할 수 있습니다. 다른 답변은 흥미로운 부수이지만 실제 질문에 대한 답변은 없습니다.

import java.awt.Graphics;
import java.awt.Color;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class Example {
    public class InnerClass extends JPanel {
        public void paint(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(getX(),getY(),getWidth(),getHeight());
            g.setColor(Color.RED);
            g.fillRect(5, 20, 195, 20);
            g.setColor(Color.BLACK);
            g.drawString("This was written by an inner class.", 10, 35);
        }
    }

    public void demonstrate() {
        InnerClass sc = new InnerClass();//<---this is key
        JFrame jf = new JFrame();
        jf.add(sc);
        jf.setSize(220, 130);
        jf.setLocation(450, 450);
        jf.show();
    }

    public static void main(String[] params) {
        Example e = new Example();//<---so is this
        e.demonstrate();//<---and this is also key
    }
}

부록 : 정적 메서드에서 정적 내부 클래스를 인스턴스화 할 수 있습니다. 이러한 종류의 코드는 정적 메서드 내에서 비 ​​정적 내부 클래스를 인스턴스화하는 데만 필요합니다.
Herbert Samuel Jennings III
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.