Backend/Java

Java - 중첩 클래스

퐁고 2023. 2. 22. 19:41
반응형

중첩 클래스

  • 클래스가 여러 클래스와 관계를 맺는 경우 독립적으로 선언하는게 좋으나 특정 클래스만 관계를 맺을 경우에는 중첩 클래스로 선언하는 것이 유지보수에 도움이 된다.
  • 클래스 내부에 선언한 클래스, 코드의 복잡성을 줄일 수 있다.
  • 멤버 클래스
    • 인스턴스(내부) 클래스
    • 정적 클래스
  • 로컬 클래스
    • 외부 클래스 메소드 내부에서 선언된다.

인스턴스(내부) 중첩 클래스

  • static 키워드를 사용하지 않고 다른 클래스 내에 정의된 클래스
  • 내부 클래스는 외부 클래스의 멤버에 접근 가능하다.
  • 내부 클래스는 외부 클래스의 내부에 존재하므로 내부 클래스를 인스턴스 하려면 외부 클래스를 인스턴스화한 후 인스턴스화 해야함.
  • 내부 멤버 클래스는 외부 클래스 내부에서 사용되므로 주로 private 접근 제한을 갖는 것이 일반적
public class A {
  private String strValue;
  private Integer intValue;

  // 내부 클래스 정의
  class B {
    public void show() {
      System.out.println("B의 show() 메서드 호출");
    }
  }

  // 내부 클래스 privateB를 private로 정의
  private class privateB {
    public void show() {
      System.out.println("privateB의 show() 메서드 호출");
    }
  }
}

public class Main {
  public static void main(String args[]) {
    // 외부 클래스를 인스턴스화 합니다.
    A a = new A();

    // 외부 클래스의 객체를 사용하여 내부 클래스의 객체를 생성합니다.
    A.B b = a.new B();

    b.show();

    // privateB가 private로 정의되었으므로 A 외부에서 접근할 수 없습니다.
    // 따라서, privateB는 A 외부에서 인스턴스화 할 수 없습니다.
  }
}

실행 결과

B**의 show() 메서드 호출**

인스턴스 생성법

// 외부 클래스 A, 내부 클래스 B
A a = new A();
A.B b = a.new B();

외부 클래스 멤버 접근법

  • this 키워드 사용
  • 외부 클래스.this.변수명으로 외부 클래스 멤버 접근
  • this.변수명은 내부 클래스 멤버를 접근
public class A {
  private String strValue;
  private Integer intValue;

  A(String strValue, Integer intValue) {
    this.strValue = strValue;
    this.intValue = intValue;
  }

  class B {
    private String strValue;
    private Integer intValue;

    B(String strValue, Integer intValue) {
      this.strValue = strValue;
      this.intValue = intValue;
    }

    public void show() {
      // 외부 클래스.this로 외부 클래스의 멤버를 접근합니다.
      System.out.println("A의 strValue: " + A.this.strValue);
      System.out.println("A의 intValue: " + A.this.intValue);
      // this만 사용하면 내부 클래스의 멤버를 나타냅니다.
      System.out.println("B의 strValue: " + this.strValue);
      System.out.println("B의 intValue: " + this.intValue);
    }
  }
}

public class Main {
  public static void main(String args[]) {
    A a = new A("Hello", 100);

    A.B b = a.new B("Bye", 200);

    b.show();
  }
}

실행 결과

A의 strValue: Hello
A의 intValue: 100
B의 strValue: Bye
B의 intValue: 200

정적 중첩 클래스

  • static 키워드를 사용하여 내부 클래스 정의
  • 일반 내부 클래스내에는 static 변수를 포함할 수 없지만, static 내부 클래스로 정의하면 가능
  • 외부 클래스 멤버를 접근할 수 없으며, 정적 중첩 클래스를 인스턴스 하기 위해 외부 클래스의 인스턴스를 생성할 필요 없다.
    • 외부 클래스 멤버를 접근할 수 없으므로, 내부 클래스는 아니다.
public class A {
  String strValue;

  static class StaticB {
    Integer intValue = 10;
    void show() {
      System.out.println("intValue: " + intValue);
      // 정적 중첩 클래스에서 외부 클래스 멤버를 접근할 수 없습니다.
      // System.out.println(OuterClass.this.strValue);
    }
  }
}

public class Main {
  public static void main(String args[]) {
    A.StaticB b = 
            new A.StaticB();
    b.show();
  }
}

실행 결과

intValue: 10

인스턴스 생성법

// 외부 클래스 A, 내부 클래스 B
A.B b = new A.B();

로컬 클래스

  • 외부 클래스의 메소드 내에 선언된 내부 클래스를 로컬 내부 클래스라 말한다.
public class A {
  public void show() {
    System.out.println("A의 show() 메서드 호출");

    // 외부 클래스의 메서드에서 내부 클래스를 정의합니다.
    class B {
      public void show() {
        System.out.println("B의 show() 메서드 호출");
      }
    }

    // 외부 클래스의 메서드에서 내부 클래스를 인스턴스화 합니다.
    B b = new B();

    b.show();
  }
}

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

    a.show();
  }
}

실행 결과

A의 show() 메서드 호출
B의 show() 메서드 호출