ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java]STEP1 - 14) 중첩 클래스와 중첩 인터페이스
    개발 공부/Java 2020. 10. 2. 14:41

     

    본 게시글은 도서 "이것이 자바다" 동영상 강의를 듣고 기록하는 TIL(Today I Learned) 입니다.
    모든 저작권은 출판사 한빛미디어와 신용권님께 있음을 알립니다.👍

     

     

    객체 지향 프로그래밍에서 클래스들은 서로 긴밀한 관계를 맺으며 상호작용합니다.

    클래스가 여러 클래스와 관계를 맺는 경우에는 독립적으로 클래스를 선언하는 것이 좋으나,

    특정 클래스와만 관계를 맺는 경우에는 클래스 내부에 중첩 클래스 형태로 선언하는 것이 좋습니다.

     

    이번 게시물에서는 클래스 안에 선언되는 중첩 클래스와 중첩 인터페이스의 개념과 사용에 대해 알아보겠습니다.

     

     

    1. 중첩 클래스(Nested Class)


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

    class ClassName {
        class NestedClassName {
         // 중첩 클래스 선언
        }
    }

     

    중첩 클래스는 클래스 내부에 선언되는 위치에 따라서 두 가지로 분류된다.

    1. 멤버 클래스 : 클래스의 멤버로서 선언되는 중첩 클래스. 인스턴스 멤버 클래스와 정적 멤버 클래스로 나뉜다.

    2. 로컬 클래스 : 메소드 내부에서 선언되는 중첩 클래스

     

    인스턴스 멤버 클래스

    • static 키워드 없이 선언된 클래스를 말한다.
    • 인스턴스 멤버 클래스에는 정적 필드와 정적 메소드를 선언할 수 없다.

    정적 멤버 클래스

    • static 키워드로 선언된 클래스를 말한다.
    • 정적 멤버 클래스에는 모든 종류의 필드와 메소드를 선언할 수 있다.

    로컬 클래스

    • 메소드 내에서 선언한 중첩 클래스를 말한다.
    • 접근 제한자(public, private) 및 static을 붙일 수 없다.
    • 로컬 클래스에는 정적 필드와 정적 메소드를 선언할 수 없다.
    • 로컬 클래스 내부에서는 바깥 클래스의 필드나 메소드를 제한 없이 사용할 수 있다.
      하지만, 메소드의 매개 변수나 로컬 변수를 로컬 클래스에서 사용할 때는 특이한 점이 있다. 아래에 설명하겠다.
    void outMethod (final int arg1, int arg2) {
        final int var1 = 1;
        int var2 = 2;
        class LocalClass {
            void method() {
                int result = arg1 + arg2 + var1 + var2;
            }
        }
    }

    자바는 매개 변수나 로컬 변수가 수정되어 값이 변경되면, 로컬 클래스에 복사해 둔 값과 달라지는 문제를
    해결하기 위해 매개 변수나 로컬 변수를 final로 선언하여 수정을 막는다.

    Java 7 까지만 해도 final 키워드를 붙인 매개 변수나 로컬 변수만 로컬 클래스에서 사용할 수 있었다.
    하지만 Java 8 부터는 final 키워드를 붙이지 않아도 컴파일러가 알아서 final의 특성을 갖도록 해준다.

    따라서 위 코드에서 LocalClass 안에서 arg1, arg2, var1, var2 가 사용되었으므로
    이 4개의 변수는 모두 final의 특성을 갖게 된다.

     

     

    중첩 클래스에서 바깥 클래스의 참조를 얻기 위해서는 this를 사용하면 된다.

    단 this만 사용하게 될 경우에는 바깥 클래스가 아니라 중첩 클래스의 객체를 참조하게 된다.

    this.필드
    this.메소드

    따라서 바깥 클래스의 참조를 얻으려면

    바깥클래스.this.필드
    바깥클래스.this.메소드

    형태로 사용하면 된다.

     


     

    2. 중첩 인터페이스(Nested Interface)


    중첩 인터페이스클래스의 멤버로 선언된 인터페이스를 말한다.

    인터페이스를 클래스 내부에서 선언하는 이유는 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해서이다.

    특히 UI 프로그래밍에서 이벤트 처리 목적으로 많이 활용된다.

    class ClassName {
        interface NestedInterfaceName {
         // 중첩 인터페이스 선언
        }
    }

     

     

    익명 객체 : 이름이 없는 객체를 말한다. 단독으로는 생성할 수 없고 클래스를 상속하거나 인터페이스를 구현해야만 생성할 수 있다.

     

    1. 익명 자식 객체 생성 (클래스 상속)

    - 자식 클래스가 재사용되지 않고, 오로지 해당 필드와 변수의 초기값으로만 사용할 경우라면 익명 자식 객체를 생성해서 초기값으로 대입하는 것이 좋은 방법이다.

    부모클래스 [필드 or 변수] = new 부모클래스(매개값) {
        //필드
        //메소드(메소드 오버라이딩 가능)
    };

    반드시 끝에 세미콜론을 붙여줘야 한다!

    익명 자식 객체에 새롭게 정의된 필드와 메소드는 익명 자식 객체 내부에서만 사용되고, 외부에서는 필드와 메소드에 접근할 수 없다.

     

     

    2. 익명 구현 객체 생성 (인터페이스 구현)

    - 구현 클래스가 재사용되지 않고, 오로지 해당 필드와 변수의 초기값으로만 사용하는 경우라면 익명 구현 객체를 초기값으로 대입하는 것이 좋다.

    인터페이스 [필드 or 변수] = new 인터페이스() {
        //인터페이스에 선언된 추상 메소드의 실체 메소드 선언
        //필드
        //메소드
    };

    반드시 끝에 세미콜론을 붙여줘야 한다!

     

    익명 객체에서도 바깥 클래스의 메소드의 매개 변수나 로컬 변수를 사용할 때 특이한 점이 있다.

    앞서 살펴보았던 로컬 클래스에서의 매개 변수와 로컬 변수 사용 시, final이 붙는다는 점과 동일하다.

    void outMethod (final int arg1, int arg2) {
        final int var1 = 1;
        int var2 = 2;
       
        인터페이스 변수 = new 인터페이스() {
            void method() {
                int result = arg1 + arg2 + var1 + var2;
            }
        };
    }

    로컬 클래스에서와 똑같이 Java 8 부터는 final 키워드를 붙이지 않아도 컴파일러가 알아서 final의 특성을 갖도록 해준다.

    따라서 위 코드에서 익명 구현 객체 안에서 arg1, arg2, var1, var2 가 사용되었으므로
    이 4개의 변수는 모두 final의 특성을 갖게 된다.

     

     

     

    본 게시글은 여기서 마치겠습니다.

    읽어주셔서 감사하고, 혹시나 틀린 부분이나 보완해야할 부분이 있다면 댓글에 남겨주세요~!

    댓글

Designed by Tistory.