[Java] 중첩 클래스, 내부 클래스 2
20. 중첩 클래스, 내부 클래스 2
지역 클래스
- 지역 클래스
- 내부 클래스 중 하나
- 코드 블럭 안에서 클래스를 선언한다.
- 바깥 클래스의 인스턴스 멤버와 지역 변수에 접근 할 수 있다.
- 인터페이스를 구현하거나, 부모 클래스를 상속할 수 있다.
변수의 생명 주기
- 클래스 변수 (static 변수)
- 메서드 영역에 존재한다.
- 자바가 클래스 정보를 읽어들이는 순간부터 프로그램 종료까지 존재한다.
- 인스턴스 변수
- 힙 영역에 존재한다.
- 소속된 인스턴스가 GC 되기 전까지 존재한다.
- 지역 변수
- 스택 영역의 스택 프레임 안에 존재한다.
- 메서드 호출 시 생성되고, 호출 종료 시 스택 프레임이 제거되면서 지역 변수도 모두 제거된다.
- 생존 주기가 짧다.
- 매개 변수도 지역 변수의 한 종류이다.
지역 클래스 인스턴스의 생존 범위
public class LocalOuterV3 {
private int outInstanceVar = 3;
public Printer process(int paramVar) {
int localVar = 1; // 지역 변수는 스택 프레임이 종료되는 순간 함께 제거된다.
class LocalPrinter implements Printer {
int value = 0;
@Override
public void print() {
System.out.println("value = " + value);
//인스턴스는 지역 변수보다 더 오래 살아남는다.
System.out.println("localVar = " + localVar);
System.out.println("paramVar = " + paramVar);
System.out.println("outInstanceVar = " + outInstanceVar);
}
}
Printer printer = new LocalPrinter();
//printer.print()를 여기서 실행하지 않고 Printer 인스턴스만 반환한다.
return printer;
}
public static void main(String[] args) {
LocalOuterV3 localOuter = new LocalOuterV3();
Printer printer = localOuter.process(2);
printer.print();
}
}
- 지역 변수인 paramVar, localVar은 process() 메서드가 실행되는 동안에만 생존할 수 있다.
- 메서드 종료 시, process()의 스택프레임이 제거되면서 두 지역변수도 함께 제거된다.
- 이 때, LocalPrinter 인스턴스는 생존한다.
- 하지만, 지역 변수의 값들이 모두 정상적으로 출력된다.
지역 클래스 - 지역 변수 캡처
- 지역 변수 캡처(Capture) : 지역 클래스의 인스턴스를 생성하는 시점에 필요한 지역 변수를 복사해서 생성한 인스턴스 안에 함께 넣어둔다.
- 지역 클래스의 인스턴스 생성 시 지역 클래스가 접근하는 지역 변수를 확인한다.
- 지역 클래스가 사용하는 지역 변수를 복사한다. (매개 변수 포함)
- 복사한 지역 변수를 인스턴스에 포함한다.
- 복사한 지역 변수를 포함한 인스턴스가 생성된다. 인스턴스를 통해 복사한 지역 변수에 접근할 수 있다.
- 복사한 지역 변수의 생명주기는 인스턴스의 생명주기와 같다.
지역 변수 - 사실상 final
- final 키워드를 사용하지 않지만, 값을 변경하지 않는 지역변수를 뜻한다.
- 만약 지역 변수의 값을 변경하게 되면 ?
- 스택 영역에 존재하는 지역 변수의 값과 인스턴스에 캡쳐한 캡처 변수의 값이 달라지는 문제가 발생한다. (동기화 문제)
- 자바는 캡처한 지역 변수의 값을 변하지 못하게 막아서 근본적으로 문제들을 차단한다.
익명 클래스
- 클래스의 이름이 없는 지역클래스 종류의 하나
- 클래스의 선언과 생성을 한 번에 처리할 수 있다.
- 지역 클래스의 선언과 생성
//선언 class LocalPrinter implements Printer { //body } //생성 Printer printer = new LocalPrinter();
- 익명 클래스 - 지역 클래스의 선언과 생성을 한 번에
Printer printer = new Printer(){ //body }
- Printer라는 이름의 인터페이스를 구현한 익명 클래스를 생성
- body 부분에 Printer 인터페이스를 구현한 코드를 작성한다.
- 지역 클래스의 선언과 생성
- 익명클래스는 부모 클래스를 상속 받거나, 인터페이스를 구현해야한다.
- 이름이 없으며, 생성자를 가질 수 없다. (기본 생성자만 사용된다.)
- 자바 내부에서 바깥 클래스 이름 + $ + 숫자로 정의된다. (ex
AnonymousOuter$1
) - 익명 클래스의 장점
- 클래스의 별도 정의가 필요없고, 추상클래스를 즉석에서 구현할 수 있어서 코드가 간결해진다.
- 익명 클래스는 단 한 번만 인스턴스를 생성할 수 있다.
- 인스턴스를 여러 번 생성하고자 하면 지역 클래스를 선언하여 사용하면 된다.
김영한의 실전 자바 중급 1편을 참고하였습니다