Local inner class(지역 내부 클래스)는 블록 내부에서 정의된 클래스이다.
정의가 된 블록(메소드) 내부에서만 사용할 수 있고, 접근 수식어(public, protected, private)는 쓸 수 없다.
외부 클래스의 멤버 변수는 모두 사용 가능하다.
public class OuterClass {
private int a = 1; // OuterClass 클래스의 멤버 변수
public void localMethod() { // OuterClass 클래스의 멤버 메소드
int b = 10; // 메소드의 지역 변수
// b = 30; <- 컴파일 오류
class LocalClass { // 메소드 내부에서 정의된 Local inner class
private int c = 100;
public void displayNum() {
System.out.println("a = " + a); // 외부 클래스의 멤버 변수
System.out.println("b = " + b); // 내부 클래스와 동일 스코프 내의 지역 변수
System.out.println("c = " + c); // 내부 클래스의 멤버 변수
}
}
LocalClass loc = new LocalClass();
// b = 50; <- 컴파일 오류
loc.displayNum();
}
}
b가 초기화 된 이후에 b 값을 변경하려고 하면, 변수 b가 사용될 때 컴파일 오류가 발생한다.
위의 코드에서 살펴보자면 b를 출력하려고 하는 곳에서 오류가 발생할 것이다.
오류 구문은 다음과 같다.
Local variable b defined in an enclosing scope must be final or effectively final
b 값을 변경하려고 하면 displayNum() 메소드에서 초기화 된 10 이 출력되어야 하는지,
바꾼 값인 50이 출력되어야 하는지 헷갈린다.
따라서 로컬 내부 클래스에서 사용 가능한 지역 변수는 반드시 한 번 초기화 된 후 값이 변경되지 않거나, final 이어야 하는 것이다.
public class Main {
public static void main(String[] args) {
System.out.println("Local Inner Class (지역 내부 클래스)\n");
OuterClass out = new OuterClass();
out.localMethod();
}
}
🤔 인터페이스와 다형성을 이용해 어떻게 지역 클래스에 정의된 메소드를 외부에서 사용할 수 있을까?
우선, 외부에서 사용하고 싶은 메소드를 선언한 인터페이스를 작성한다.
메소드의 반환 타입은 앞서 정의한 인터페이스 타입으로 정의한다.
로컬 클래스는 인터페이스를 구현(implements)하도록 정의한다.
로컬 클래스의 인스턴스를 생성하고 반환한다.
public class Person {
private String name;
public Person(String name) {
this.name = name.;
}
public MyReadable createInstance(int age) {
class PersonWithAge implements MyReadable {
@Override
public void readInfo() {
System.out.println("이름 : " + name);
System.out.println("나이 : " + age);
}
}
MyReadable person = new PersonWithAge(); // 다형성 (자손 타입을 부모가 받으므로)
return person;
}
}
interface MyReadable {
public abstract void readInfo();
}
public class Main {
public static void main(String[] args) {
System.out.println("Local 내부 클래스의 활용\n");
Person person = new Person("홍길동");
MyReadable r = person.craeteInstance(20);
r.readInfo();
}
}
이와 같은 방식으로 사용하고 싶은 메소드 readInfo()를 포함하고 있는 MyReadable 인터페이스를 생성하고, PersonWithAge(로컬 내부 클래스)에서 해당 인터페이스를 implements 하여 구현하면 지역 클래스에서 정의된 메소드(readInfo())를 사용할 수 있다.