JAVA/JAVA

Java | Inner Class 내부 클래스 & Anonymous class 익명 클래스

pathas 2020. 2. 4. 17:25

Inner Class 내부 클래스

클래스 내부에 작성하는 클래스

  • 내부 클래스는 외부 클래스의 접근 제어자에 상관 없이 멤버변수, 메소드에 접근 가능
  • 외부 클래스에서 내부 클래스에 접근하기 위해서는 내부 클래스 객체를 생성해야 함

이름이 있는 내부 클래스

내부 클래스에 이름이 있는 경우, 일반 클래스와 동일함
다른 클래스의 내부에 있다는 점과 main()에서 클래스를 생성하는 방식만 다름

외부 클래스의 멤버 변수 및 메소드에 편리하게 접근하기 위해 사용


main() 메소드에서 내부 클래스 객체 생성법

Outer클래스명.Inner클래스명 Inner객체명 = Outer객체명.new Inner클래스명()

// 외부 클래스 객체 생성
    Outer out = new Outer();
// 내부 클래스 객체 생성
    Outer.Inner in = out.new Inner();

사용례

package j200204;

public class Outer {
    // 멤버 변수
    int a;

    // 생성자
    public Outer() {
        // 멤버 변수 초기화
        a = 10;
    }

    public void aa() {
        System.out.println("aa 메소드 호출");
        // 메소드 내부에서 내부 클래스 객체 생성 및 메소드 호출
        Inner in = new Inner();
        in.cc();
    }

    public void bb() {
        System.out.println("bb 메소드 호출");
    }

    // ========= Inner Class =========
    public class Inner {
        // 내부 클래스 멤버 변수
        int ax;

        // 내부 클래스 생성자
        public Inner() {
            ax = 15;
        }

        // 내부 클래스 메소드
        public void cc() {
            System.out.println("내부 클래스 cc 메소드 호출");
            System.out.println("외부 a: " + a + ", 내부 ax: " + ax);
            bb();
        }
    }

    public static void main(String[] args) {
        // Outer 클래스 객체 생성
        Outer out = new Outer();

        // main()에서 Inner 클래스 생성
        Outer.Inner oi = out.new Inner();
        
        System.out.println("==내부 클래스 멤버 변수==");
        
        // 내부 클래스 객체 oi의 멤버 변수 ax출력
        System.out.println("ax: " + oi.ax);
        
        System.out.println("====메소드 호출====");
        
        // 외부 클래스 메소드 호출
        // 메소드 호출 순서 out.aa -> in.cc -> out.bb
        out.aa();
        
         /*
         ==내부 클래스 멤버 변수==
         ax: 15
         ====메소드 호출====
         aa 메소드 호출
         내부 클래스 cc 메소드 호출
         외부 a: 10, 내부 ax: 15
         bb 메소드 호출
         */
    }

}

Anonymous inner class 익명 내부 클래스

클래스의 이름이 없는 경우로
상속받은 추상클래스 또는 인터페이스를 바로 객체로 생성해서 반환함

  • 단 하나의 추상 클래스 또는 단 하나의 인터페이스를 바로 생성할 수 있음
  • 클래스 마지막에 세미콜론(;)을 사용해서 익명 내부 클래스가 끝났다는 것을 표현
  • 인터페이스나 추상 클래스 자료형으로 변수를 선언한 후
    익명 내부 클래스를 생성해 변수에 대입할 수 있음
  • 메소드 내부에 작성해서 메소드 반환형을 해당 인터페이스/추상클래스로 지정할 수도 있음
  • 인터페이스와 추상 클래스 내부의 모든 추상 메소드를 반드시 오버라이딩 해야 함

형식

new 부모 추상클래스명(){
    // 부모 추상클래스 추상 메소드 오버라이딩
};

new 부모 인터페이스명(){
    // 부모 인터페이스 메소드 오버라이딩
};

사용례

OuterInter.java

OuterInter 인터페이스가 선언된 파일

package j200204;

public interface OuterInter {

    public void interPrint();

}

OuterInner.java

추상 클래스 Abs를 선언하고
외부 클래스 OuterInner 내부에 추상 클래스 및 인터페이스 객체 생성
package j200204;

// 추상 클래스 선언
abstract class Abs {

    // 추상 메소드
    abstract public void absPrint();

    // 일반 메소드
    public void print() {
        System.out.println("추상 클래스 일반 메소드 호출");
    }
}

// 외부 클래스
public class OuterInner {

    // 추상 클래스 상속 내부 익명 클래스 객체 생성
    // 추상 클래스를 상속했기 때문에 자료형은 추상 클래스를 따름
    Abs abs = new Abs() {
        public void absPrint() {
            System.out.println("추상 클래스 상속 내부 익명 클래스");
        }
    };

    // 인터페이스 구현 내부 익명 클래스 객체 생성
    // 인터페이스를 구현했기 때문에 자료형은 인터페이스를 따름
    OuterInter oi = new OuterInter() {
        public void interPrint() {
            System.out.println("인터페이스 구현 내부 익명 클래스 ");
        }
    };

    public static void main(String[] args) {

        // 외부 클래스 객체 생성
        OuterInner outin = new OuterInner();

        // 외부 클래스 객체에서 인터페이스 객체의 재정의된 interPrint() 메소드 호출
        outin.oi.interPrint();

        // 추상 클래스 객체의 재정의된 absPrint() 메소드 호출
        outin.abs.absPrint();

        // 추상 클래스 객체의 일반 메소드 역시 호출 가능
        outin.abs.print();
        
        /*
        인터페이스 구현 내부 익명 클래스 
        추상 클래스 상속 내부 익명 클래스
        추상 클래스 일반 메소드 호출
        */
    }

}

클래스 내부에 또 다른 클래스를 작성하는 내부 클래스와
내부 클래스에 이름이 없는 경우인 익명 내부 클래스에 대해 알아보았습니다.

이름이 있는 내부 클래스의 경우 외부 클래스의 멤버 변수 및 메소드에 보다 편리하게 접근하기 위해 많이 사용되고,

익명 내부 클래스의 경우 이전에 GUI 구현시 많이 사용되었다고 합니다.