[Java]-Nested Classes(1)

Nested Classes

무엇인가?

Nested Class(중첩 클래스)는 또 다른 클래스 내부에 정의된 클래스를 말합니다. Inner class라고 하기도 하지만 보통 Nested class라고 한다고 합니다.(교수님 피셜)

이때 또 다른 클래스를 Outer Class(외부 클래스), 그 안에 정의된 클래스를 Nested Class(중첩 클래스)라고 합니다.

종류 4가지

// 관계도 그려서 넣기

  • Non-Static Nested Classes(Inner Classes)
    • (Regular) Inner class
    • Local inner class
    • Anonymous inner class
  • Static nested class

사용하면 얻는 이점

//1, 3 예시 그림 그려서 넣기

  • 같은 패키지 내에 있는 다른 클래스들로부터 Nested class로 정의한 클래스를 숨길 수 있습니다. 하나의 패키지 내에서 클래스들끼리 이뤄진 캡슐화를 겹겹이 할 수 있습니다.
  • 보통 관련되어 있는 내용을 Nested class로 작성하기 때문에 조직적이게 작성할 수 있습니다. 그래서 좀 더 가독성이 좋고, 유지보수하기 좋습니다.
  • Nested class 중에서 Inner class는 Inner class가 정의된 클래스 내의 모든 데이터에 접근할 수 있습니다. private도 포함입니다.

Non-Static Nested Classes

무엇인가?

외부 클래스 내부에 Static없이 비정적으로 정의하는 중첩 클래스입니다. 이런 클래스들을 Inner Class(내부 클래스), Non-Static Member Class(비정적 멤버 클래스)라고 합니다. 칭하는 말이 여러가지여서 저도 놀랐습니다.. 저는 내부 클래스라고 하겠습니다.

Local Inner class와 Anoymous inner class도 여기에 속하기는 하지만 보통 내부 클래스라고 하면 Local Inner class와 Anoymous inner class을 제외한 내부 클래스를 말하는 것입니다.

정의

public class OuterClass {
    private int num = 8;

    public class InnerClass{
        public int inner_num = 7;
    }

    InnerClass inner = new InnerClass();
}

이렇게 외부 클래스 내에 static 없이 클래스를 정의하면 됩니다.

객체 생성

  • 외부 클래스 내에서 인스턴스 생성할 때
public class OuterClass {
    private int num = 8;

    public class InnerClass{
        //생략
    }

    InnerClass inner = new InnerClass();
}
  • 외부 클래스 외에 다른 클래스에서 인스턴스 생성할 때
    • 내부 클래스가 non-private일때만 이렇게 생성 가능합니다.
public class OuterClass2 {
    public void main(String[] avg){
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();
    }
}

멤버 변수에 접근

  • 외부클래스의 멤버에 접근하기
    • 내부클래스에서는 외부클래스의 private 멤버에도 접근할 수 있습니다.
public class OuterClass {
    private int num = 8;

    public class InnerClass{
        public int inner_num = 7;
        public int inner_num2 = num; // 직접 access 가능
    }
}
  • 외부 클래스의 멤버와 같은 이름을 사용할 때
    • 이때는 내부 클래스에서는 내부 클래스에 선언된 멤버를 가리키게 됩니다.
    • 외부 클래스의 멤버를 호출할 때는 OuterclassName.this 이렇게 호출해야 합니다.
public class OuterClass {
    private int num = 8;

    public class InnerClass{
        public int inner_num = 7;
        public int num; // 변수 이름을 같도록 하면 inner class의 변수를 가리키게 됨. 이 상태에서 바깥의 것을 가리킬 수는 없을까?
        public int inner_num2 = num; // 내부 클래스의 num이 assign된다.

        public int inner_num3 = OuterClass.this.num; // 이렇게 하면 외부 클래스의 num을 가져옴.
    }

}

static과의 관계

  • 내부 클래스의 목적이 외부 클래스 내에 혹은 외부 클래스를 통해 인스턴스 객체를 만들어서 사용하기 위함이기 때문에, static 변수나 static 메소드를 안에 만들지 않아야 합니다.
    • 이러한 목적 때문에 내부 클래스는 외부 클래스를 참조하고 있습니다. 이는 메모리 누수 문제를 초래할 수 있다고 합니다. 많은 분들이 이에 관한 포스팅을 해주셔서 관련 글을 찾아보시면 좋을 것 같습니다.
      멤버 클래스는 되도록 static으로 만들라
  • 외부 클래스에 선언되어 있는 static method에서는 외부클래스의 객체를 통해서만이 내부클래스의 객체에 접근할 수 있습니다.
    • 이는 JVM의 메모리 구조를 보면 알 수 있습니다. static 관련 변수, 메소드는 Method 영역 안의 외부 클래스 변수에 저장이 됩니다. 내부 클래스 객체는 생성이 되면 Heap 영역에 저장됩니다. 그래서 외부 클래스에 정의된 static 메소드를 통해 내부 클래스 객체에 접근하려고 하면 내부 클래스의 참조값을 가지고 있는 외부 클래스 객체가 있어야 하는 것입니다. Static 변수 저장 참고
    • 아래 코드와 같이 static 메소드에 외부 클래스 객체를 전달해서 내부 클래스에 접근하도록 해야 합니다.
public class OuterClass {
    private int num = 8;

    public class InnerClass{
        public int inner_num = 7;
    }

    InnerClass inner = new InnerClass();

    public static void getInner_num(OuterClass outerClass){//파라미터로 외부 클래스 객체의 레퍼런스 변수를 받고 있습니다.
        outerClass.num = outerClass.inner.inner_num;
    }
}

좋은 웹페이지 즐겨찾기