2018-5-6 TIL 네스티드클래스

네스티드(Nested)클래스와 이너(Inner)클래스

class Outer {
	class Nested { .. } //네스티드 클래스
}
  • 클래스 내에 정의 된 클래스를 네스티드 클래스라 하고, 이를 감싸는 클래스를 가리켜 외부 클래스 라고 한다.

네스티드 클래스의 구분

  • 네스티드 클래스는 static의 선언 여부를 기준으로 나뉜다.
    1. Static 네스티드 클래스
    2. Non-Static 네스티드 클래스 : 이를 이너클래스라 한다.
class OuterClass {
	static class StaticNestedClass { .. } // Static 네스티드 클래스
}

class OuterClass {
	class InnerClass { ... } // Non-static 네스티드 클래스, 이너 클래스
}

이너클래스는 정의되는 위치나 특성에 따라 세종류로 나뉜다.

  1. 멤버 이너 클래스(Member Inner Class)
  2. 로컬 이너 클래스(Local Inner Class)
  3. 익명 이너 클래스(Anonymous Inner Class)

Static 네스티드 클래스

  • static선언이 갖는 특성이 반영하는 클래스이다. 따라서 자신을 감싸는 외부클래스의 인스턴스와 상관없이 Static 네스티드 클래스의 인스턴스 생성이 가능하다.
package yoon;

class Outer {
    private static int num = 0;
    static class Nested1 { // static 네스티드 클래스
        void add(int n) { num += n; }
    }
    static class Nested2 { // Static 네스티드 클래스
        int get() {return num;}
    }
}

public class StaticNested {
    public static void main(String[] args) {
        Outer.Nested1 nst1 = new Outer.Nested1();
        nst1.add(5);
        Outer.Nested2 nst2 = new Outer.Nested2();
        System.out.println(nst2.get());
    }
}
//result
5
  • Outer클래스 내에 두개의 Static 네스티드 클래스가 정의 되어있다.
    class Outer {
      private static int num = 0;
    
      static class Nested1 { // static 네스티드 클래스
          void add(int n) { num += n; }
      }
    
      static class Nested2 { // Static 네스티드 클래스
          int get() {return num;}
      }
    }
    
  • 위의 Nested1, Nested2 클래스 내에서는 Outer의 static멤버 num에 접근하고 있다. private로 선언이 되어있어도 접근이 가능하다. 따라서 Outer의 static멤버 num은 Nested1과 Nested2의 모든 인스턴스가 공유하게 된다. 그리고 이것이 ‘Static 네스티드 클래스’가 갖는 주요 특징이다.
  • Outer.Nested1 nst1 = new Outer.Nested1()처럼 인스턴스를 생성해야한다.
  • Static 네스티드 클래스의 인스턴스 생성은 외부 클래스의 인스턴스 생성과 무관하다.

    Static네스티드 클래스 내에서 외부 클래스의 인스턴스 변수와 메소드에 접근이 불가능하다. 즉 Static 네스티드 클래스 내에서는 외부 클래스에 static으로 선언된 변수와 메소드에만 접근이 가능하다.

이너(Inner)클래스 구분 : 네스티드 클래스 중에서 static 선언이 붙지 않은 클래스를 가리켜 이너 클래스라고 한다. 이너 클래스는 다음의 셋으로 나뉜다.

  1. 멤버클래스
  2. 로컬클래스
  3. 익명클래스
  • 멤버클래스 : 인스턴스변수, 인스턴스메소드와 동일한 위치에 정의
  • 로컬클래스 : 중괄호 내에, 특히 메소드내에 정의
class Outer {
	class MemberInner {...} // 멤버클래스

    void method() {
    	class LocalInner {...} // 로컬클래스
    }
}
  • 반면 익명클래스는 이름이 존재하지 않는 클래스이므로 위의 두 클래스와 혼동할 일이 없다.

멤버클래스

package yoon;

class Outer2 {
    private int num = 0;

    class Member {
        void add(int n) { num += n; }
        int get() { return num; }
    }
}

public class MemberInner {
    public static void main(String[] args) {
        Outer2 o1 = new Outer2();
        Outer2 o2 = new Outer2();

        // o1기반으로 인스턴스 생성
        Outer2.Member o1m1 = o1.new Member();
        Outer2.Member o1m2 = o1.new Member();

        // o2 기반으로 인스턴스 생성
        Outer2.Member o2m1 = o2.new Member();
        Outer2.Member o2m2 = o2.new Member();

        // o1 기반으로 생성된 두 인스턴스 메소드 호출
        o1m1.add(5);
        System.out.println(o1m2.get());

        // o2 기반으로 생성된 인스턴스 메소드 호출
        o2m1.add(7);
        System.out.println(o2m2.get());
    }
}
//reuslt
5
7
  • 위 예제에서 정의하는 ‘멤버클래스’는 다음과 같다
    class Outer2 {
      private int num = 0;
    
      class Member {
          void add(int n) { num += n; }
          int get() { return num; }
      }
    }
    
  • 멤버 클래스의 인스턴스는 외부 클래스 인스턴스에 종속적이다.

  • Outer o1 = new Outer(); 에서 먼저 인스턴스를 생성
  • Outer.member o1m1 = o1.new Member();와 같이 인스턴스를 생성을 했다. Outer인스턴스 없이 Member의 인스턴스 생성이 불가능하다.

멤버클래스는 언제 사용하는가? 멤버클래스는 클래스의 정의를 감추어야 할때 유용하게 사용한다.

package yoon;

interface Printable2 {
    void print();
}

class Papers {
    private String con;
    public Papers(String s) {
        con = s;
    }

    public Printable2 getPrinter() {
        return new Printer(); // 멤버 클래스 인스턴스 생성 및 반환
    }

    private class Printer implements Printable2 { // 멤버 클래스 정의
        public void print() {
            System.out.println(con);
        }
    }
}

public class UseMemberInner {
    public static void main(String[] args) {
        Papers p = new Papers("서류 내용 : 행복합니다.");
        Printable2 prn = p.getPrinter();
        prn.print();
    }
}
//result
서류 내용 : 행복합니다.
  • 이 인터페이를 구현하는 Printer클래스를 Papers클래스 내에 정의를 했다.
  • Printer 클래스는 private으로 선언이 되었다. 멤버클래스가 private으로 선언이 되면, 이 클래스 정의를 감싸는 클래스 내에서만 인스턴스 생성이 가능하다.
  • Papers p
Written on May 6, 2018