[Java] 11. OOP - 내부 클래스(Inner Class), 익명 클래스

2024. 7. 7. 22:41·Java/Core

내부 클래스(inner class)

  • 내부 클래스는 AWT나 Swing같은 GUI Application 이벤트 처리를 제외하고는 잘 쓰이지 않는다.

  • 이런 게 이렇게 작동하는구나 정도만 이해하고 넘어가자

내부 클래스란?

  • 내부 클래스: 클래스 내에 선언된 클래스

  • 클래스에 다른 클래스 선언하는 이유 : 두 클래스가 서로 긴밀한 관계에 있기 때문

    • 내부 클래스로 선언하면 두 클래스의 멤버들 간에 서로 쉽게 접근할 수 있다는 장점이 있고, 외부에는 불필요한 클래스를 감춰 코드 복잡성을 줄일 수 있다.
class A {
        //
        class B {
                //
        }
}
  • class A는 외부 클래스, class B는 내부 클래스이다.

    • 이 때 내부 클래스인 B는 외부 클래스인 A를 제외하고는 다른 클래스에서 잘 사용되지 않는 것이어야 한다.

내부 클래스의 종류와 특징

  • 내부 클래스의 종류는 변수의 선언위치에 따른 종류와 같다.

    • 인스턴스 클래스 : 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 인스턴스 멤버처럼 다루어진다.

    • 스태틱 클래스 : 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static 인스턴스 멤버처럼 다루어진다.

    • 지역 클래스 : 외부 클래스의 메서드나 초기화 블럭 안에서 선언하며, 선언된 영역 내부에서만 사용될 수 있다.

    • 익명 클래스 : 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용)

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

  • 내부 클래스의 인스턴스 클래스와 스태틱 클래스는 멤버변수와 같은 성질을 갖는다

    • 즉, 내부 클래스가 외부 클래스의 멤버와 같이 간주된다
  • 내부 클래스도 클래스이기 때문에 abstract나 final과 같은 제어자를 사용할 수 있고, 멤버 변수처럼 private나 protected과 같은 접근 제어자도 사용이 가능하다

Example 7.31

class InnerEx1 {
    class InstanceInner {
        int iv = 100;
//        static int cv = 100;        // 컴파일 에러. staic변수를 선언할 수 없음
        final static int CONST = 100;        // final static은 상수이므로 허용
    }

    static class StaticInner {
        int iv = 100;
        static int cv = 200;        // static클래스만 static멤버를 정의할 수 있음
    }

    void myMethod() {
        class LocalInner {
            int iv = 300;
//            static int cv = 300;    // 에러. static변수를 선언할 수 없음
            final static int CONST = 300;    // final static은 상수이므로 허용
        }
    }

    public static void main(String args[]) {
        System.out.println(InstanceInner.CONST);
        System.out.println(StaticInner.cv);
    }
}
  • 내부 클래스 중에서 스태틱 클래스만 static 멤버를 가질 수 있다.

    • 드물지만 내부 클래스에 static 변수를 선언해야 한다면 스태틱 클래스로 선언해야 한다
  • 다만 final과 static이 동시에 붙은 변수는 상수이므로 모든 내부 클래스에서 정의가 가능하다

Example 7.33

class InnerEx3 {
    private int outerIv = 0;
    static int outerCv = 0;

    class InstanceInner {
        int iiv = outerIv;    // 외부클래스의 private멤버도 접근 가능
        int iiv2 = outerCv;
    }

    static class StaticInner {
        // static클래스는 외부클래스의 인스턴스멤버에 접근할 수 없음
//        int siv = outerIv;
        static int scv = outerCv;
    }

    void myMethod() {
        int lv = 0;
        final int LV = 0;    // JDK1.8부터 final 생략 가능

        class LocalInner {
            int liv = outerIv;    // myMethod()가 static인 경우 컴파일 에러.
            int liv2 = outerCv;

            // 외부클래스의 지역변수는 final이 붙은 변수(상수)만 접근 가능
            int liv3 = lv;    // 컴파일 에러. (JDK1.8부터 에러 아님)
            int liv4 = LV;    // O
        }
    }
}
  • 인스턴스 클래스는 외부 클래스의 인스턴스 멤버이기 때문에 인스턴스 변수 outerIv와 static변수 outerCvf를 모두 사용할 수 있다.

    • 심지어 접근제어자가 private라도 가능하다
  • 스태틱 클래스는 단지 static 멤버인 outerCv만 사용 가능하다

  • 지역 클래스는 외부 클래스의 인스턴스멤버와 static멤버를 모두 사용할 수 있으며, 지역 클래스가 포함된 메서드에 정의된 지역 변수도 사용할 수 있다.

    • 단, final이 붙은 지역변수만 접근가능한데, 메서드가 수행을 마쳐서 지역변수가 소멸된 시점에도, 지역 클래스의 인스턴스가 소멸된 지역변수를 참조하려는 경우가 발생할 수 있기 때문이다.
    • 주의) JDK 1.8부터 지역 클래스에서 접근하는 지역 변수 앞에 final을 생략할 수 있게 바뀌었다. 이걸 모르고 해당 변수 값을 바꾸면 컴파일 에러가 발생한다

Example 7.34

class Outer {
    class InstanceInner {
        int iv = 100;
    }

    static class StaticInner {
        int iv = 200;
        static int cv = 300;
    }

    void myMethod() {
        class LocalInner {
            int iv = 400;
        }
    }
}

class InnerEx4 {
    public static void main(String[] args) {
        // 인스턴스클래스의 인스턴스를 생성하려면
        // 외부클래스의 인스턴스를 먼저 생성해야 한다.
        Outer oc = new Outer();
        Outer.InstanceInner ii = oc.new InstanceInner();

        System.out.println("ii.iv : " + ii.iv);
        System.out.println("Outer.StaticInner.cv : " + Outer.StaticInner.cv);

        // static내부클래스의 인스턴스는 외부클래스를 먼저 생성하지 않아도 된다.
        Outer.StaticInner si = new Outer.StaticInner();
        System.out.println("si.iv : " + si.iv);
    }
}
  • 외부 클래스가 아닌 다른 클래스에서 내부 클래스를 생성하고 내부 클래스의 멤버에 접근하는 예제인데, 이런 경우가 발생하게 코드를 작성하면 안 됩니다!

Example 7.35

class Outer {
    int value = 10;    // Outer.this.value

    class Inner {
        int value = 20;    // this.value

        void method1() {
            int value = 30;
            System.out.println("           value : " + value);
            System.out.println("      this.value : " + this.value);
            System.out.println("Outer.this.value : " + Outer.this.value);
        }
    }    // Inner클래스의 끝
}    // Outer클래스의 끝

class InnerEx5 {
    public static void main(String args[]) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.method1();
    }
}    // InnerEx5 끝
  • 내부 클래스와 외부 클래스에 선언된 변수의 이름이 같을 때 변수 앞에 'this'또는 '외부 클래스명.this'를 붙여서 서로 구별할 수 있다.

익명 클래스(anonymous class)

  • 다른 내부 클래스들과 다르게 이름이 없다.

  • 클래스의 선언과 객체의 생성을 동시에 하기 때문에 단 한번만 사용될 수 있고, 오직 하나의 객체만을 생성할 수 있는 일회용 클래스이다.

new 조상클래스이름() {
    // 멤버 선언
}
or
new 구현인터페이스이름() {
    // 멤버 선언
}
  • 이름이 없기 때문에 생성자도 가질 수 없다.

  • 조상클래스의 이름이나 구현하고자 하는 인터페이스의 이름을 사용해서 정의하기 때문에 하나의 클래스로 상속받는 동시에 인터페이스를 구현하거나, 둘 이상의 인터페이스를 구현할 수 없다.

    • 오직 단 하나의 클래스를 상속받거나, 단 하나의 인터페이스만을 구현할 수 있다.

내부 클래스 -> 익명 클래스

내부 클래스

import java.awt.*;
import java.awt.event.*;

class InnerEx7 {
    public static void main(String[] args) {
        Button b = new Button("Start");
        b.addActionListener(new EventHandler());
    }
}

class EventHandler implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        System.out.println("ActionEvent occurred!!!");
    }
}

익명 클래스

import java.awt.*;
import java.awt.event.*;

class InnerEx8 {
    public static void main(String[] args) {
        Button b = new Button("Start");
        b.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.out.println("ActionEvent occured!!!");
                }
            }    // 익명클래스의 끝
        );
    }    // main의 끝
}

참조) Java의 정석 3rd edition(남궁성, 도우출판)

'Java > Core' 카테고리의 다른 글

[Java] 13. 예외 처리(Exception handling)(2) - try-catch 문  (0) 2024.07.09
[Java] 12. 예외 처리(Exception handling)(1) - 예외 처리란?  (0) 2024.07.09
[Java] 10. OOP - 인터페이스(Interface)  (0) 2024.07.07
[Java] 09. OOP - 추상 클래스(abstract class)  (0) 2024.06.24
[Java] 08. OOP - 다형성(polymorphism)  (0) 2024.06.24
'Java/Core' 카테고리의 다른 글
  • [Java] 13. 예외 처리(Exception handling)(2) - try-catch 문
  • [Java] 12. 예외 처리(Exception handling)(1) - 예외 처리란?
  • [Java] 10. OOP - 인터페이스(Interface)
  • [Java] 09. OOP - 추상 클래스(abstract class)
lumana
lumana
배움을 나누는 공간 https://github.com/bebeis
  • lumana
    Brute force Study
    lumana
  • 전체
    오늘
    어제
    • 분류 전체보기 (465) N
      • 개발 일지 (28)
        • Performance (0)
        • TroubleShooting (1)
        • Refactoring (0)
        • Code Style, Convetion (0)
        • Architecture (1)
      • Software Engineering (36) N
        • Test (8)
        • 이론 (18)
        • Clean Code (10) N
      • Java (72)
        • Basic (5)
        • Core (21)
        • Collection (7)
        • 멀티스레드&동시성 (13)
        • IO, Network (8)
        • Reflection, Annotation (3)
        • Modern Java(8~) (13)
        • JVM (2)
      • Spring (53)
        • Framework (12)
        • MVC (23)
        • Transaction (3)
        • AOP (11)
        • Boot (0)
        • AI (0)
      • DB Access (16)
        • Jdbc (1)
        • JdbcTemplate (0)
        • JPA (14)
        • Spring Data JPA (0)
        • QueryDSL (0)
      • Computer Science (130)
        • Data Structure (27)
        • OS (14)
        • Database (10)
        • Network (21)
        • 컴퓨터구조 (6)
        • 시스템 프로그래밍 (23)
        • Algorithm (29)
      • HTTP (8)
      • Infra (1)
        • Docker (1)
      • 프로그래밍언어론 (15)
      • Programming Language(Sub) (77)
        • Kotlin (1)
        • Python (25)
        • C++ (51)
        • JavaScript (0)
      • FE (11)
        • HTML (1)
        • CSS (9)
        • React (0)
        • Application (1)
      • Unix_Linux (0)
        • Common (0)
      • PS (13)
        • BOJ (7)
        • Tip (3)
        • 프로그래머스 (0)
        • CodeForce (0)
      • Book Review (4)
      • Math (3)
        • Linear Algebra (3)
      • AI (7)
        • DL (0)
        • ML (0)
        • DA (0)
        • Concepts (7)
      • 프리코스 (4)
      • Project Review (6)
      • LegacyPosts (11)
      • 모니터 (0)
      • Diary (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
lumana
[Java] 11. OOP - 내부 클래스(Inner Class), 익명 클래스
상단으로

티스토리툴바