본문 바로가기
언어/JAVA

[중첩 클래스]

by 코딩맛집 2023. 2. 5.

9.1 중첩 클래스

중첩 클래스란 클래스 내부에 선언한 클래스를 말한다.

객체 지향 프로그램에서는 클래스 간에 서로 긴밀한 관계를 맺고 상호작용한다. 클래스가 여러 클래스와 관계를 맺는 경우에는 독립적으로 선언하는 것이 좋으나, 특정 클래스만 관계를 맺을 경우에는 중첩 클래스로 선언하는 것이 유지보수에 도움이 되는 경우가 많다.

 

장점

1. 클래스의 멤버를 쉽게 사용할 수 있다.

2. 외부에는 중첩 관계 클래스를 감춤으로써 코드의 복잡성을 줄일 수 있다.

3. 유지보수에 유용할 경우가 있다.

 

중첩 클래스는 선언하는 위치에 따라 두 가지로 분류된다. 클래스 멤버로서 선언되는 중첩 클래스를 멤버 클래스라고 하고, 메소드 내부에서 선언되는 중첩 클래스를 로컬 클래스라고 한다.

중첩 클래스도 하나의 클래스이기 때문에 컴파일하면 바이트코드 파일(.class)이 별도로 생성된다.

멤버 클래스일 경우 바이트코드 파일의 이름은 다음과 같이 결정된다.

로컬 클래스일 경우에는 다음과 같이 $1이 포함된 바이트코드 파일이 생성된다.

 

9.2 인스턴스 멤버 클래스

인스턴스 멤버 클래스는 class 앞에 static 키워드 없이 선언된 클래스를 말한다.

[public] class A {
    [public | private] class B {
    }
}

인스턴스 멤버 클래스는 인스턴스 필드와 메소드만 선언이 가능하고 정적 필드와 정적 메소드는  Java 17부터 선언이 가능하다.

 

접근 제한자에 따른 인스턴스 멤버 클래스의 접근 범위는 다음과 같다.

인스턴스 멤버 클래스는 B는 주로 A 클래스 내부에서 사용되므로 private 접근 제한을 갖는 것이 일반적이다. 

 


예제는 https://github.com/mdmdr8/JavaEx/tree/main/src 에서 확인해 주세요~

 

GitHub - mdmdr8/JavaEx: 이것이 자바다. 연습 문제

이것이 자바다. 연습 문제. Contribute to mdmdr8/JavaEx development by creating an account on GitHub.

github.com


 

9.3 정적 멤버 클래스

정적 멤버 클래스는 class 앞에 static 키워드와 함께 A 클래스의 멤버로 선언된 B 클래스를 말한다.

[public] class A {
    [public | private] static class B {
    }
}

접근 제한자에 따른 인스턴스 멤버 클래스의 접근 범위는 다음과 같다.

정적 멤버 클래스 B는 A 클래스 내부에서 사용되기도 하지만, A 클래스 외부에서 A와 함께 사용되는 경우가 많기 때문에 주로 default 또는 public 접근 제한을 가진다. B 객체는 A 클래스 내부 어디든 객체를 생성할 수 있다.

 

A 클래스 외부에서 B 객체를 생성하려면 A 객체 생성 없이 A 클래스로 접근해서 B 객체를 생성할 수 있다.

A.B b = new A.B();

 

9.4 로컬 클래스

생성자 또는 메소드 내부에서 다음과 같이 선언된 클래스를 로컬 클래스라고 한다. 로컬 클래스는 생성자와 메소드가 실행될 동안에만 객체를 생성할 수 있다. 로컬 클래스 B 내부에는 일반 클래스와 같이 필드, 생성자, 메소드 선언이 올 수 있다. 정적 필드와 정적 메소드는  Java 17부터 선언이 가능하다.

package ch09.sec04.exam02;

public class A {
    void useB(){
        class B{
            int field1 = 1;

            static int field2 = 2;

            B(){
                System.out.println("B-생성자 실행");
            }

            void method1(){
                System.out.println("B-메소드1 실행");
            }

            static void method2(){
                System.out.println("B-메소드2 실행");
            }
        }
        B b = new B();

        System.out.println(b.field1);
        b.method1();

        System.out.println(B.field2);
        B.method2();
    }
}
package ch09.sec04.exam02;

public class AExample {
    public static void main(String[] args) {
        A a = new A();

        a.useB();
    }
}

로컬 변수를 로컬 클래스에서 사용할 경우 로컬 변수는 final 특성을 갖게 되므로 값을 읽을 수만 있고 수정할 수 없게 된다. 이것은 로컬 클래스 내부에서 값을 변경하지 못하도록 제한하기 떄문이다.

Java8 이후부터는 명시적으로 final 키워드를 붙이지 않아도 되지만, 로컬 변수에 final 키워드를 추가해서 final 변수임을 확히 할 수도 있다. 

 

9.5 바깥 멤버 접근

중첩 클래스는 바깥 클래스와 긴밀한 관계를 맺으면서 바깥 클래스의 멤버(필드, 메소드)에 접근할 수 있다. 하지만 중첩 클래스가 어떻게 선언되었느냐에 따라 접근 제한이 있을 수 있다.

 

바깥 클래스의 멤버 접근 제한

정적 멤버 클래스 내부에서는 바깥 클래스의 필드와 메소드를 사용할 때 제한이 따른다.

package ch09.sec05.exam01;

public class A {
    
    int field1;
    void method1() {}
    
    static int field2;
    static void method2(){}
    
    class B {
        void method(){
            field1 = 10;
            method1();
            field2 = 10;
            method2();
        }
    }
    
    static class C {
        void method(){
            field2 = 10;
            method2();
        }
    }
}

 

바깥 클래스의 객체 접근

중첩 클래스 내부에서 this는 해당 중첩 클래스의 객체를 말한다. 만약 중첩 클래스 내부에서 바깥 클래스의 객체를 얻으려면 바깥 클래스 이름에 this를 붙여주면 된다.

바깥클래스이름.this -> 바깥객체
package ch09.sec05.exam02;

public class A {
    String field = "A-field";

    void method(){
        System.out.println("A-method");
    }

    class B {
        // B 인스턴스 필드
        String field = "B-field";

        // B 인스턴스 메소드
        void method(){
            System.out.println("B-method");
        }

        // B 인스턴스 메소드
        void print(){
            // B 객체의 필드와 메소드 사용
            System.out.println(this.field);
            this.method();

            System.out.println(A.this.field);
            A.this.method();
        }
    }
    void useB(){
        B b = new B();
        b.print();
    }
}

'언어 > JAVA' 카테고리의 다른 글

[chapter 9] 확인 문제  (0) 2023.02.06
[중첩 인터페이스] 익명 객체(익명 자식 객체, 익명 구현 객체)  (0) 2023.02.05
[chapter5] 확인 문제  (2) 2023.01.30
[인터페이스]  (0) 2023.01.30
[상속]  (0) 2023.01.28