병훈's Blog

[Java] 내부/익명 클래스 본문

Java

[Java] 내부/익명 클래스

thdqudgns 2022. 10. 5. 00:49

내부 클래스 (inner class)

내부클래스의 장점

  • 내부클래스에서 외부클래스의 멤버들에 쉽게 접근할 수 있다.
    외부클래스의 private 도 접근 가능
  • 코드의 복잡성을 줄일 수 있다. (캡슐화)
    내부클래스를 외부클래스에서만 사용한다면 넣어라
  • 멤버들 간의 접근이 용이해진다.
    객체생성 없이 내부클래스에서 외부클래스의 멤버를 전역변수처럼 사용함.
  • 내부클래스의 접근제어자는 변수처럼 protected와 private까지도 가능하다.

내부클래스 특징

1. 멤버변수와 사용법이 같다.

내부클래스의 특징은 iv, cv, lv 처럼 쓰인다는 것이다.
인스턴스 클래스, 스태틱 클래스, 지역 클래스, + 익명클래스
(지역클래스: 메소드 안의 클래스 -> 다른 곳에서는 사용 못함)
(익명클래스: 클래스의 선언과 객체생성을 동시에 하는 이름없는 클래스)

 

static 멤버가 인스턴스멤버를 사용할 수 없듯이
static 클래스가 인스턴스 클래스 및 인스턴스 멤버를 사용할 수 없다.

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

      static class StaticInner { 
            int iv = 200; 
            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); 
      } 
} 

2. 내부클래스 객체 생성

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);

         // 스태틱 내부 클래스의 인스턴스는 외부 클래스를 먼저 생성하지 않아도 된다.
        Outer.StaticInner si = new Outer.StaticInner();    // [외부클래스명].[내부클래스명]
        System.out.println("si.iv : "+ si.iv);
    }
}

3. 내부클래스 멤버 접근

같은 이름의 변수가 있을 때 접근방법

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);    // 외부클래스의 전역변수 
            // [외부클래스명].this.[변수명]
        }
    } // Inner클래스의 끝
} // Outer클래스의 끝

class InnerEx5 {
    public static void main(String args[]) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.method1();
    }
} // InnerEx5 끝

익명클래스 (anonymous class)

이름이 없는 일회용 클래스.
선언과 객체 생성을 동시에 함.
하나의 객체만 생성 가능함.

new 조상클래스명() {
    // 멤버 선언
}

또는

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());    // EventHandler 클래스 선언
    }
}

class EventHandler implements ActionListener {    // EventHandler 클래스 코드
    public void actionPerformed(ActionEvent e) {
        System.out.println("ActionEvent occurred!!!");
    }
}

여기서 EventHandler 클래스를 익명클래스로 만드는 방법은

  1. 매개변수에 위치한 new EventHandler()
    구현할 인터페이스명인 new ActionListener() 로 바꾼다.
  2. EventHandler 의 구현부를 그대로 이어붙인다.
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 occurred!!!");
                                    } // 구현부 내부 메소드의 끝
                            } // 익명 클래스 구현부 끝
        );    // addActionListener 메소드의 끝
    } // main메서드의 끝
} // InnerEx8클래스의 끝

오늘의 내용은 여기까지입니다.
생각보다 별거 없죠?ㅎㅎ

728x90
728x90

'Java' 카테고리의 다른 글

SOLID 원칙  (0) 2023.10.25
[Java] 예외처리 (exception handling)  (0) 2022.10.06
[Java] 인터페이스 (interface)  (1) 2022.10.04
[Java] 추상클래스 (abstract class)  (0) 2022.09.29
[Java] 다형성2 (Polymorphism)  (1) 2022.09.29