7-8. 내부 클래스

Hyun Jun·2022년 1월 22일
0

자바의 정석

목록 보기
33/52
post-thumbnail
post-custom-banner

내부 클래스

클래스 내에 선언하는 클래스로, 일반적인 클래스와 유사함

실제 사용 빈도는 낮은 편

 

개념

클래스 내에 다른 클래스를 선언하는 이유는, 둘의 관계가 긴밀하기 때문

  • 양쪽 멤버들에 서로 쉽게 접근 가능

  • 외부에 불필요한 클래스를 감출 수 있음 (코드 복잡성 감소)

class A {
    ...
    class B {
        ...
    }
    ...
}

바깥쪽인 A를 외부 클래스, 안쪽인 B를 내부 클래스라고 부름

 

내부 클래스의 종류와 특징

선언 위치에 따라 구분

구분 특징
인스턴스 클래스
(instance class)
- 멤버변수 선언위치에 선언
- 인스턴스 멤버처럼 다뤄짐
스태틱 클래스
(static class)
- 멤버변수 선언위치에 선언
- 스태틱 멤버처럼 다뤄짐
지역 클래스
(local class)
- 메서드나 초기화 블럭 안에 선언
- 선언된 영역 내부에서만 사용 가능
익명 클래스
(anonymous class)
- 클래스의 선언과 인스턴스 생성을 동시에 함
- 일회용

 

내부 클래스의 선언

같은 위치에 선언된 변수와 동일한 스코프 및 접근성을 가짐

class Outer {
    int instanceVar = 7;
    static int classVar = 7;

    void instanceMethod() {
        int localVar = 7;
    }
}
class Outer {
    class InstanceClass {}
    static class StaticClass {}

    void instanceMethod() {
        class LocalClass {}
    }
}

 

내부 클래스의 제어자와 접근성

내부 클래스는 외부 클래스의 멤버로 간주되어, 멤버에 사용할 수 있는 public, protected, private 같은 접근 제어자나 final을 붙일 수 있음

그와 동시에 클래스이기도 하기 때문에 abstractstatic 같은 제어자도 사용 가능함

단, static 내부 클래스만 static 멤버를 가질 수 있음

대신 final static은 상수이므로, 모든 내부 클래스에서 사용 가능

 

클래스의 멤버들에 대해 존재하는 다음 규칙은

  • 인스턴스 멤버 → 같은 클래스 내의 static 멤버와 인스턴스 멤버 모두 직접 사용 가능

  • static 멤버 → 같은 클래스 내의 static 멤버 사용 가능. 인스턴스 멤버는 해당 클래스의 인스턴스 생성 없이는 사용 불가능

  • 지역 멤버 → 같은 클래스 내의 static 멤버와 인스턴스 멤버 모두 직접 사용 가능

내부 클래스에 대해서도 동일하게 적용됨

  • 인스턴스 클래스 → 외부 클래스의 static 멤버와 인스턴스 멤버 모두 직접 사용 가능

  • static 클래스 → 외부 클래스의 static 멤버 사용 가능. 인스턴스 멤버는 외부 클래스의 인스턴스 생성 없이는 사용 불가능

  • 지역 클래스 → 같은 클래스 내의 static 멤버와 인스턴스 멤버 모두 직접 사용 가능.

    단, 자신이 포함된 메서드에 존재하는 지역 변수를 사용할 때는 상수만 사용 가능

    이유: 지역 클래스는 지역 변수를 참조할 때, 사실은 그 변수들의 사본을 만들어 사용하기 때문에 사본의 정확성을 위해 원본 지역변수의 값이 불변해야함

    (JDK 1.8부터는 지역 변수에 명시적으로 final을 안붙여도 초기화 이후에 값의 수정이 없는 변수면 상수로 간주함)

class Outer {
    private int outerIV = 0;
    static int outerCV = 0;

    class InstanceInner {
        int innerIV = outerIV;
        int innverIV2 = outerCV;
    } // 인스턴스 클래스에서 외부 클래스의 인스턴스 변수와 클래스 변수 모두 접근 가능

    static class StaticInner {
        // int staticInnerIV = outerIV; 스태틱 클래스에서는 외부 클래스의 인스턴스 변수 접근 불가
        static int staticInnerCV = outerCV; // 클래스 변수는 접근 가능
    }

    void someMethod() {
        int outerLV = 0; // 초기화 이후 값이 변하지 않으므로 상수 취급 (final 생략 가능)
        int outerLV2 = 0;
        ...
        outerLV2 = 0; // 초기화 이후 값이 변했으므로 상수가 아님

        class LocalInner {
            int localInnerIV = outerIV;
            int localInnerIV2 = outerCV;
            int localInnerIV3 = outerLV; // 지역 클래스는 상수만 접근 가능
            // int localInnerIV4 = outerLV2; 상수가 아닌 경우는 접근 불가
        }
    }
}

 

외부 클래스와 내부 클래스에 선언된 변수명이 같을 때는

  • 외부 클래스의 변수 → 외부클래스명.this.변수명

  • 내부 클래스의 변수 → this.변수명

으로 구분함

 

익명 클래스

  • 선언과 인스턴스 생성을 동시에 함

  • 이름이 없기 때문에 한 번만 사용되는 일회용 클래스

  • 생성자 보유 불가

  • 1개의 클래스만 상속받거나, 1개의 인터페이스만 구현할 수 있음

  • 조상 클래스를 상속받거나 인터페이스를 구현할 때, 굳이 새 클래스를 만들지 않고 일회성 객체를 만드는 거라 보면 됨.

new 상속받을조상클래스명() {
    ...
}
// 또는
new 구현할인터페이스명() {
    ...
}

 

class Outer {
    Object instanceVar = new Object() {
        void method() {
            ...
        }
    }; // 인스턴스 익명 클래스
    static Object classVar = new Object() {
        void method() {
            ...
        }
    }; // 스태틱 익명 클래스

    void outerMethod() {
        Object localVar = new Object() {
            void method() {
                ...
            }
        }; // 지역 익명 클래스
    }
}
profile
Back-end Engineer 👨‍💻
post-custom-banner

0개의 댓글