본문 바로가기

Language/Java

중첩 클래스(Nested Class) [자바 4대 중첩 클래스]


자바 4대 중첩 클래스

1. 중첩 클래스 (Inner Class)


  □ 정의
    - 하나의 클래스 내부에 또 다른 클래스가 내포되어 있는 상태. (클래스 관리의 효율을 높임.)

  □ 특징
    - 중첩되는 클래스는 하나 이상 가능.
    - Outer 클래스 멤버를 Inner 클래스에서 사용 가능.
    - Outer 클래스에서 Inner 클래스 멤버 사용 불가능. (사용하고 싶으면 객체를 직접 발생 시켜야 함.)
    - 일반 중첩 클래스 내부에서는 static과 관련된 멤버를 선언할 수 없음.

  □ 형식

 class Outer {
    내용부;
    class Inner { 
        내용부;
    }
 }


  □ 중첩 클래스 객체 생성

 Outer 객체1 = new Outer();  // Outer 클래스 객체 생성.
 Outer.Inner 객체2 = 객체1.new Inner();  // Inner 클래스 객체 생성.


  □ 생성된 클래스 파일 형식
    - Inner 클래스는 '$'라는 기호로 표시.

 Outer_클래스명.class
 Outer_클래스명$Inner_클래스명.class  // ex> Outer$Inner.class


  □ 예제
    ■ Inner 클래스에서 Outer 클래스 멤버 접근 예제

/* Exam01 class */

public class Exam01 {
    
    private int x = 100;
    
    class Inner {
        private int y = 200;
        
        public void display() {
            System.out.println("x : " + x);
            System.out.println("y : " + y);
        }
    }

}
/* Exam02 class */

public class Exam02 {
    public static void main(String[] args) {
        Exam01 outer = new Exam01();
        Exam01.Inner inner = outer.new Inner();
        
        inner.display();
    }
}
/* output */

x : 100
y : 200

    ■ Outer 클래스에서 Inner 클래스 멤버 접근 예제

/* Exam03 class */

public class Exam03 {
    
    private int x = 100;
    
    public void display() {
        System.out.println("x : " + x);
//        System.out.println("y : " + y); // compile error.
        
        Inner in = new Inner(); // 원형 : Exam03.Inner in = this.new Inner();
        System.out.println("y : " + in.y);
    }
    
    class Inner {
        private int y = 200;
    }

}
/* Exam04 class */

public class Exam04 {
    public static void main(String[] args) {
        Exam03 out = new Exam03();
        
        out.display();
    }
}
/* output */

x : 100
y : 200


/* Exam05 class */

public class Exam05 {
    
    private static int x = 100;
    
    class Inner {
        private int x = 200;
        
        public void display() {
            System.out.println("x1 : " + Exam05.x);
            System.out.println("x2 : " + this.x);
        }
    }

}
/* Exam06 class */

public class Exam06 {
    public static void main(String[] args) {
        Exam05 out = new Exam05();
        Exam05.Inner in = out.new Inner();
        
        in.display();
    }
}
/* output */

x1 : 100
x2 : 200



2. 정적 중첩 클래스 (Static Inner Class)

  □ 정의
    - 중첩 클래스 내부에서 static과 관련된 멤버를 선언할 수 있는 클래스.
   
  □ 특징
    - 클래스의 이름 앞에 static 예약어가 붙음.
    - static의 특성상 객체를 독립적으로 만들 수 있음.
    - static 멤버를 선언할 수도 있고 static 메서드도 만들어 사용할 수 있음.
    - Outer 클래스의 static 멤버만 Inner에서 사용할 수 있음.

  □ 형식

 class Outer {
    내용부;
    static class Inner {
        내용부;
    }
 }


  □ 객체 생성 방법

 Outer.Inner 객체 = new Outer.Inner();

    -  Outer 클래스의 객체가 없어도 Inner 클래스의 객체 생성 가능.

  □ 예제
    ■ Outer 클래스의 static 멤버 Inner 클래스에서 사용 예제

/* Exam07 class */

public class Exam07 {
    
    private int x = 100;
    private static int z = 300;
    
    static class Inner {
        private int y = 200;
        
        public void display() {
//            System.out.println("x : " + x); // compile error. (일반 멤버는 사용할 수 없음.)
            System.out.println("z : " + z);
            System.out.println("y : " + y);
        }
    }

}
/* Exam08 class */

public class Exam08 {
    public static void main(String[] args) {
        Exam07.Inner in = new Exam07.Inner();
        
        in.display();
    }
}
/* output */

z : 300
y : 200



3. 지역 중첩 클래스 (Local Inner Class)

  □ 정의
    - 특정 메서드에 한정적인 용도로 사용하는 클래스.

  □ 특징
    - 접근 제한자와 지정 예약어를 사용할 수 없는 형태.
    - 일반 중첩 클래스의 형태와 유사하기 때문에 static 멤버를 선언하지 못함.
    - 객체 생성은 외부에서 할 수 없음.

  □ 형식

 class Outer {
    내용부;
    method() {
        내용부;
        class Inner {
             내용부;
        }
    }
 }


  □ 생성된 클래스 파일 형식
    - Inner 클래스는 '$'라는 기호로 표시.

 Outer_클래스명.class
 Outer_클래스명$숫자Inner_클래스명.class  // ex> Outer$1Inner.class


  □ 예제
    ■ 메서드 안에서 Inner 클래스 사용 예제

/* Exam09 class */

public class Exam09 {
    public static void main(String[] args) {
        int x = 100;
        
        class Inner {
            int y = 200;
        }
        
        Inner in = new Inner();
        
        System.out.println("x : " + x);
        System.out.println("y : " + in.y);
    }

}
/* output */

x : 100
y : 200

    ■ 메서드 안 Inner 클래스가 메서드의 멤버 사용 예제

/* Exam10 class */

public class Exam10 {
    public static void main(String[] args) {
        final int x = 300;  // final로 선언해야 Inner 클래스에서 사용 가능.
        
        class Inner {
            int y = 400;
            
            public void display() {
                System.out.println("x : " + x);
                System.out.println("y : " + y);
            }
        }
        
        Inner in = new Inner();
        in.display();
    }

}
/* output */

x : 300
y : 400



4. 익명 중첩 클래스 (Anonymous Inner Class)

  □ 정의
    - 지역 중첩 클래스의 변형된 형태.
    - 기존 클래스의 특정 메서드를 오버라이딩하여 원하는 형태로 재정의하여 사용회는 방식.

  □ 특징

    - class 예약어와 클래스명을 가지지 않고 단지 instance의 생성과 내용부의 정의만 가짐.
    - 여기에 사용되는 중첩 클래스는 이미 기존에 존재하는 클래스이어함.
    - 내부 클래스는 생성자를 작성할 수 없음. (생성자를 작성하게 되면 컴파일 에러 발생.)
    - 외부 멤버 중 final만 포함.

  □ 형식

 class Inner {
    내용부;
 }

 class Outer {
     내용부;
    method() {
        내용부;
        new Inner() {
            내용부;
        };
    }
 }


  □ 생성된 클래스 파일 형식
    - 클래스 이름이 없기 때문에 숫자로 그 클래스를 표시.

 Outer_클래스명$숫자.class  // ex> Outer$2.class


  □ 예제

/* Exam11 class */

public class Exam11 {
    
    int y = 200;
    
    public Exam11() {
        this.display();
    }
    
    public void display() {
        System.out.println("Exam11 class");
    }

}
/* Exam12 class */

public class Exam12 {
    public static void main(String[] args) {
        final int x = 100;  // final로 선언해야 Inner 클래스에서 사용 가능.
        
        new Exam11() {
            public void display() {  // overriding
                System.out.println("Default 생성자");
                System.out.println("x : " + x);
                System.out.println("y : " + y);
            }
        };
    }

}
/* output */

Default 생성자
x : 100
y : 200


/* Exam13 class */

public class Exam13 {
    
    public void aaa() {
        System.out.println("aaa");
    }
    
    public void bbb() {
        System.out.println("bbb");
    }
    
    public void ccc() {
        System.out.println("ccc");
    }
}
/* Exam14 class */

public class Exam14 {
    public static void main(String[] args) {
        Exam13 in = new Exam13() {
            public void bbb() {
                System.out.println("DDD");
                ddd();  // 익명 중첩 클래스 안에서 생성한 메소드 사용 가능.
            }
            
            public void ddd() {
                System.out.println("ddd");
            }
        };
        
        in.aaa();
        in.bbb();
        in.ccc();
//        in.ddd();  // 익명 중첩 클래스 안에서 생성한 메소드 사용 불가능.
    }
    

}
/* output */

aaa
DDD
ddd
ccc





한방 테스트 코드


public class NestedClassTest {

private int aa = 20;

static private int bb = 30;

public NestedClassTest(){}

//정적 중첩 클래스

static class StaticInnerClass{

public int a = 10;

static public int b = 10; 

public StaticInnerClass(){}

public int getAA(){ //Static 변수만 접근 가능

return bb;

}

}

//중첩 클래스

class InnerClass{

public int a = 10;

//static public int b = 10;  //Static 선언 안됨

public InnerClass(){}

public int getAA(){

return aa;

}

}

//지역 중첩 클래스를 위한 메소드

void methodLocalInnerClass(){

class LocalInnerClass{

int a = 10;

//static int b = 20; //Static선언 안됨

}

System.out.println("Local Inner Class: "+new LocalInnerClass().a);

}

//익명 중첩 클래스를 위한 메소드

void methodAnonymousInnerClass(){

System.out.println("Anonymous Inner Class: ");

}

public static void main(String[] args) {

NestedClassTest outer = new NestedClassTest(){

//오버라이딩할때 aaa()를 참조

void methodAnonymousInnerClass(){

System.out.println("Anonymous Inner Class: "+aaa());

}

int aaa(){

return 77;

}

};

//중첩클래스들 선언 방식

StaticInnerClass sinner = new NestedClassTest.StaticInnerClass();

System.out.println("Static Inner Class: "+sinner.a);

NestedClassTest.InnerClass inner = outer.new InnerClass();

System.out.println("Inner Class: "+inner.a);

outer.methodLocalInnerClass();

outer.methodAnonymousInnerClass();

//outer.aaa();  //사용불가

}

}


'Language > Java' 카테고리의 다른 글

Java Garbage Collection  (0) 2014.02.27
Interface vs Abstract  (0) 2014.02.27
JAVA 접근 제한자 (public, private, protected, default)  (1) 2014.02.27
Java Reflection 개념 및 사용법  (4) 2014.02.27
JAVA ThreadLocal  (0) 2014.02.27