관리 메뉴

너와 나의 스토리

[Java] 중첩 클래스와 중첩 인터페이스 본문

Programming Language/Java

[Java] 중첩 클래스와 중첩 인터페이스

노는게제일좋아! 2021. 4. 19. 23:30
반응형

중첩 클래스(Nested Class)

  • 어떤 클래스가 특정 클래스와만 관계를 맺을 경우에는 특정 클래스 내부에 해당 클래스를 선언하는 것이 좋다.
  • 중첩 클래스를 사용하면 멤버들을 서로 쉽게 접근할 수 있다.
class ClassName {
  class NestedClassName {
  }
}

 

 

중첩 인터페이스(Nested Interface)

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

 

 

중첩 클래스

  • 멤버 클래스: 클래스의 멤버로서 선언되는 중첩 클래스
    • 멤버 클래스는 클래스나 객체가 사용 중이라면 언제든지 재사용이 가능하다.
    • 인스턴스 멤버 클래스의 경우 인스턴스 필드와 메서드만 선언이 가능하고 정적 필드와 메서드는 선언할 수 없다.
    • 정적 멤버 클래스는 모든 종류의 필드와 메서드를 선언할 수 있다.
<인스턴스 멤버 클래스> - A 객체를 생성해야만 B 중첩 클래스를 사용할 수 있다.

class A {
  class B {
    int field1;
    // static i nt field2; 정적 필드 선언 불가
    
    void method1() {}
    // static void method2() {} 정적 메서드 선언 불가
  }
}

 

<정적 멤버 클래스> - A 클래스로 B 중첩 클래스에 바로 접근할 수 있다.

class A {
  static class B {
    int field1;
    static i nt field2;
    
    void method1() {}
    static void method2() {}
  }
}
  • 로컬 클래스: 메소드 내부에서 선언되는 중첩 클래스
    • 로컬 클래스는 메서드 실행 시에만 사용되고, 메서드가 실행 종료되면 없어진다.
    • 접근 제한자(public, private) 및 static을 붙일 수 없다. -> 로컬에서만 사용하므로 선언할 필요가 없는 것
<로컬 클래스>

void method() {
  class B {
    int field1;
    // static i nt field2; 정적 필드 선언 불가
    
    void method1() {}
    // static void method2() {} 정적 메서드 선언 불가
  }
  B b = new B();
  b.field1 = 3;
  d.method1();
}

 

 

중첩 클래스에서 바깥 클래스 참조 얻기

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

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

  class Nested {
    String field = "Nested-field";

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

    void print() {
        // 중첩 객체(Nested) 참조
        System.out.println(this.field);
        this.method();

        // 바깥 객체(Outter) 참조
        System.out.println(Outter.this.field);
        Outter.this.method();
    }
  }
}

 

 

중첩 인터페이스

public class Button {
  OnClickListener listener;

  void setOnClickListener(OnclickListener listener) {
      this.listener = listener;
  }

  void touch() {
      listener.onClick();
  }

  interface OnClickListener {
    void onClick();
  }
}
  • Setter 메서드로 구현 객체를 받아 필드에 대입한다.
public class ButtonExample {
  public static void main(String[] args) {
    Button btn = new Button();

    btn.setOnClickListener(new CallListener());
    btn.touch();

    btn.setOnClickListener(new MessageListener());
    btn.touch();
  }
}
  • 어떤 구현 객체를 설정하느냐에 따라 touch() 메서드의 실행 결과가 달라진다.

 

 

중첩 클래스의 접근 제한

  • 로컬 클래스 내부에서는 바깥 클래스의 필드나 메서드를 제한 없이 사용할 수 있다.
  • 문제는 매개 변수나 로컬 변수를 로컬 클래스에서 사용할 때이다.
  • 로컬 클래스의 객체는 메서드 실행이 끝나도 힙 메모리에 존재해서 계속 사용될 수 있다. 
  • 하지만 매개 변수나 로컬 변수는 메서드 실행이 끝나면 스택 메모리에서 사라지기 때문에 로컬 객체에서 사용할 경우 문제가 발생한다. 
  • 이러한 문제를 막기 위해 로컬 클래스에서 사용 가능한 것은 final로 선언된 매개 변수와 로컬 변수뿐이다. 
  • 자바 7 이전에는 final 키워드 없이 선언된 값에 접근하면 컴파일 에러가 발생했지만, 자바 8 이후로는 final 키워드가 없는 값에 접근해도 컴파일 에러가 발생하지 않는다.
    • 로컬 클래스에서 사용된 매개 변수와 로컬 변수는 모두 자동으로 final 특성을 갖게되기 때문이다.
public class Outter {
  String field = "Outter-field";

  void method1() {
      System.out.println("Outter-field");
  }	

  public void method2(int arg){
    int localVar = 1;
    // arg = 100  final 특성을 가지기 때문에 수정 불가
    // localVar = 100;  final 특성을 가지기 때문에 수정 불가

    class Inner {
      public void method() {
          int result = arg + localVar;	
      }
    }
  }
}

 

 

출처:

- [이것이 자바다]

반응형
Comments