Inner Class(내부 클래스)
1. Member inner class(멤버 내부 클래스): 다른 클래스 내부에서 선언된 클래스
2. Static inner class(static 내부 클래스): 다른 클래스의 내부에서 static으로 선언된 클래스
3. Local class(지역 클래스)
public class Inner01Main {
public static void main(String[] args) {
System.out.println("Member Inner Class(멤버 내부 클래스)");
// 외부 클래스의 인스턴스 생성
TestOuter out = new TestOuter(100);
// 멤버 내부 클래스의 인스턴스 생성
// 멤버 내부 클래스의 이름: [외부클래스 이름].[멤버 내부클래스 이름]
// [외부클래스 이름].[내부클래스 이름] 참조변수 =
// [외부클래스 인스턴스].new 내부클래스 생성자();
TestOuter.TestInner in=out.new TestInner(111);
in.printOuterValue(); //100
in.printInnerValue(); //111
// 하나의 외부 클래스 인스턴스를 이용해서
// 멤버 내부 클래스의 인스턴스는 여러개를 생성할 수 있다.
System.out.println();
TestOuter.TestInner in2 = out.new TestInner(123);
in2.printOuterValue(); //마찬가지로 동일한 out 쓰는 중 : 100
in2.printInnerValue(); //123
System.out.println();
TestOuter.TestInner in7;
in7 = new TestOuter(30).new TestInner(330);
in7.printOuterValue(); //30
in7.printInnerValue(); //330
} // end main()
} // end class Inner01Main
// 클래스: 멤버 변수들 (+ 생성자들) + 멤버 메소드들 = 데이터 타입
public class TestOuter {
// 멤버 변수:
private int outerValue;
// 생성자:
public TestOuter() {
}
public TestOuter(int outerValue) {
this.outerValue = outerValue;
}
// 메소드:
public int getValue() {
return outerValue;
}
public void setValue(int outerValue) {
this.outerValue = outerValue;
}
// Inner class 정의
// (수식어) class 클래스이름 {...}
public class TestInner {
//필드
private int innerValue;
//생성자
public TestInner() {
}
public TestInner(int innerValue) {
this.innerValue = innerValue;
}
//메소드
public void printOuterValue() {
//내부 클래스는 외부 클래스의 필드 직접 접근 가능
System.out.println("outerValue: " + outerValue);
}
public void printInnerValue() {
System.out.println("innerValue: " + innerValue);
}
}//end inner class
} // end class TestOuter
상속 관계로 묶을 수는 없지만, A라는 객체가 생성된 이후에야 존재할 수 있는 B라는 객체가 있다고 한다면, B를 A의 멤버 '내부 클래스'로 선언한다.
ex) 컴퓨터-CPU / 메모리, 자동차-타이어
반면, '햄버거 세트 메뉴' 객체의 경우, 햄버거 객체와 콜라 객체는 별개의 객체로도 존재 가능하니까 '햄버거' 와 '콜라' 는 '세트메뉴' 객체의 '멤버변수'로 붙도록 하는게 낫다.
is-a : 상속관계
has-a (종속) : 멤버내부클래스
has-a (독립) : 멤버변수
다른 클래스의 내부에서 멤버로 정의된 클래스인데, static 키워드가 사용된 내부 클래스 (static inner class)
static:
중첩 클래스의 인스턴스 생성:
effectively final 변수란?
1. final로 선언된 변수, 또는
2. 한 번 초기화가 된 이후로 값이 변경되지 않은 변수(Java 8에서 도입)
public class Local01Main {
public static void main(String[] args) {
System.out.println("Local Inner Class(지역 내부 클래스)");
TestOuter out=new TestOuter();
out.localMethod(400);
} // end main()
} // end class Local01Main
public class TestOuter {
//TestOuter 클래스의 멤버 변수
private int num1 = 100; // ①
// TestOuter 클래스의 멤버 메소드
public void localMethod(final int num4) {
int num2 = 200; //localMethod() 지역변수
// num4 *= 2; //오류: final임
// LocalMethod 메소드 안에 정의된 Local inner class
class TestLocal {
private int num3 = 300; // Local class의 필드
//class에 접근제어자 못 붙임. 내부는 괜찮음
public void showNumbers() {
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
System.out.println("num3 = " + num3);
System.out.println("num4 = " + num4);
}
}
TestLocal local = new TestLocal();
//num2 = 400;
// num2 값을 변경하면.. 아래 showNumbers()에선
// 200 이 찍혀야 하나? 400이 찍혀야 하나?
// 그래서 로컬내부클래스에서 사용 가능한 지역의 변수는
// 반드시 effectively final 이어야 한다
// 즉 한번 초기화 된후 값이 변경되지 않거나, final 이어야 한다.
local.showNumbers();
} // end localMethod()
} // end class TestOuter