Java & Kotlin

[Java 기능] 중첩 클래스 (2)

Sue 2022. 2. 14. 18:58

지역 내부 클래스

  • 메서드 내부에 정의하여 사용하는 클래스
  • 메서드의 호출이 끝나면 지역변수의 유효성은 사라짐
  • 반면 지역 내부 클래스 안에서 사용되는 메서드의 지역 변수나 매개변수는 final로 선언됨

 

AnonymousInnerTest.java
  • Runnable : 클래스를 쓰레드화 하는데 필요한 run 메서드를 구현할 때 사용하는 인터페이스
  • 지역변수는 메서드가 호출될 때 생성되고 호출이 끝나면 소멸됨 (스택 메모리에 존재)
  • 하지만 지역 내부 클래스의 run() 메서드는 getRunnable 메서드가 호출되고 난 후에도 또 호출될 수 있음 
  • 따라서 컴파일러가 자동으로 매개변수와 지역변수를 final로 설정함 → 변수의 값을 바꿀 수 없음
  • MyRunnable 클래스를 사용하려면 getRunnable 메서드를 호출하여 생성된 개체를 반환받아야 함 (직접 생성x)
package ch01;

class Outer2{
	
	int outNum = 100;
	static int sNum = 200;
	
	Runnable getRunnable(int i) {
		
		int num = 10;
		
		class MyRunnable implements Runnable {	// 지역 내부 클래스
			
				int localNum = 1000;
				@Override
				public void run() {
					
//					i = 50; 값 변경시 오류
//					num = 20;
					
					System.out.println("i =" + i);
					System.out.println("num =" + num);
					System.out.println("localNum =" + localNum);
					
					System.out.println("outNum =" + outNum + "(외부 클래스 인스턴스 변수)");
					System.out.println("Outer.sNum =" + Outer2.sNum + "(외부 클래스 정적 변수)");
					
				}
				
			}
		return new MyRunnable();
	}
}

public class AnonymousInnerTest {

	public static void main(String[] args) {
		
		Outer2 out = new Outer2();
		Runnable runner = out.getRunnable(100);	// getRunnable 메서드 실행하여 개체 반환
		
		runner.run();
	}

}

 

수행 결과
i =100
num =10
localNum =1000
outNum =100(외부 클래스 인스턴스 변수)
Outer.sNum =200(외부 클래스 정적 변수)

 

익명 내부 클래스

  • 이름이 없는 클래스
  • 클래스의 이름을 생략하고 주로 하나의 인터페이스 혹은 추상 클래스를 구현하여 반환
  • 인터페이스나 추상 클래스의 자료형 변수에 직접 대입하여 클래스를 생성하거나 지역 내부 클래스의 메서드 내부에서 생성하여 반환할 수 있음
  • 안드로이드 프로그래밍에서 widget의 이벤트 핸들러에 활용됨

 

익명 내부 클래스
  • 위의 코드에서 MyRunnable 클래스는 다른 곳에서 호출 될 일이 없음 (클래스 이름의 필요성 x)
Runnable getRunnable(int i) {

    int num = 10;

    return new Runnable() {	// 1. Runnable 인터페이스를 구현하여 바로 반환

            int localNum = 1000;
            @Override
            public void run() {

//		i = 50; 값 변경시 오류
//		num = 20;

                System.out.println("i =" + i);
                System.out.println("num =" + num);
                System.out.println("localNum =" + localNum);

                System.out.println("outNum =" + outNum + "(외부 클래스 인스턴스 변수)");
                System.out.println("Outer.sNum =" + Outer2.sNum + "(외부 클래스 정적 변수)");

            }

        };
}

Runnable runnable = new Runnable() {	// 2. Runnable 인터페이스에 대한 인스턴스 변수를 선언해서 implement

    @Override
    public void run() {

        System.out.println("Runnable class");
    }

};

public class AnonymousInnerTest {

	public static void main(String[] args) {
		
		Outer2 out = new Outer2();
		Runnable runner = out.getRunnable(100);
		
		runner.run();
		
		out.runnable.run();
	}

}

 

수행 결과
i =100
num =10
localNum =1000
outNum =100(외부 클래스 인스턴스 변수)
Outer.sNum =200(외부 클래스 정적 변수)
Runnable class