참고 도서
Do it 자바 완전정복
클래스 내부에 포함되는 이너 클래스는 인스턴스 멤버 이너 클래스, 정적 멤버 이너 클래스
그리고 지역 이너 클래스로 나뉜다
인스턴스 멤버 이너 클래스는 이름에서도 알 수 있는 것처럼 인스턴스, 즉 객체 내부의 멤버의
형태로 존재한다. 이때 자신을 감싸고 있는 아우터 클래스의 모든 접근 지정자의 멤버에 접근
할 수 있다
class 아우터 클래스{
class 이너 클래스{
}
}
이너 클래스는 독립적으로 사용할 수 없고, 반드시 아우터 클래스를 이용해야만 사용할 수 있다.
인스턴스 멤버 이너 클래스는 아우터 클래스의 객체 내부에 존재한다. 따라서 이너 클래스의
객체를 생성하기 위해서는 먼저 아우터 클래스의 객체를 생성해야 한다.
이후 생성한 아우터 클래스 객체의 참조 변수를 이용해 객체 내부에 있는 이너 클래스의
생성자를 다음과 같이 호출한다
[아우터 클래스] [아우터 클래스 참조 변수] = new 아우터 클래스();
[아우터 클래스].[이너 클래스] [이너 클래스 참조 변수] = [아우터 클래스 참조 변수].new 이너 클래스()
class A{
class B{
}
}
A a = new A();
A.B b = a.new B();
class Test{
public int a = 1;
protected int b = 2;
int c = 3;
private int d = 4;
void say(){
System.out.println("A 클래스 메서드 say()");
}
//인스턴스 이너 클래스
class Test2{
void say2(){
//아우터 클래스의 필드 사용
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
//아우터 클래스의 메서드 호출
say();
}
}
}
public static void main(String[] args){
//아우터 클래스 객체 생성
Test t = new Test();
//멤버 사용
Test.Test2 tt = t.new Test2();
tt.say2(); // 1, 2, 3, 4 A 클래스 메서드 say()
}
이너 클래스 내부에서 아우터 클래스의 멤버를 참조하고 싶다면 아우터 클래스명.this를
명시적으로 붙여 사용한다
class A{
int a = 3;
int b = 4;
void abc() {
System.out.println("A 클래스 메서드");
}
class B{
int a = 5;
int b =6 ;
void abc() {
System.out.println("B 클래스 메서드");
}
void bcd() {
System.out.println(a);
System.out.println(b);
abc();
System.out.println(A.this.a);
System.out.println(A.this.b);
A.this.abc();
}
}
}
public static void main(String[] args){
//아우터 클래스 객체 생성
A a = new A();
//이너 클래스 객체 생성
A.B b = a.new B();
b.bcd();
/*
5
6
B 클래스 메서드
3
4
A 클래스 메서드
*/
}
정적 멤버 이너 클래스는 이너 클래스 앞에 static 키워드가 포함된 이너 클래스다.
정적 메서드와 동일하게 아우터 클래스의 정적 멤버에만 접근할 수 있다.
정적 이너 클래스도 말 그대로 정적 멤버이므로 클래스명으로 바로 접근할 수 있다.
[아우터 클래스].[이너 클래스] [이너 클래스 참조 변수] = new [아우터 클래스] .이너 클래스();
class A{
static class B{
}
}
A.B b = new A.B();
class A{
int a = 3;
static int b = 4;
void method1() {
System.out.println("instance method");
}
static void method2() {
System.out.println("static method");
}
static class B{
void abc() {
//필드 사용
// System.out.println(a); // 정적 이너 클래스는 아우터 클래스의 정적 멤버만 사용 가능
System.out.println(b);
//메서드 호출
//method1(); // 정적 이너 클래스는 아우터 클래스의 정적 멤버만 사용 가능
method2();
}
}
}
//정적 이너 클래스의 객체 생성
A.B b = new A.B();
//메서드 호출
b.bcd(); //4, static method 출력
지역 이너 클래스는 클래스의 멤버가 아닌 메서드 내에서 정의되는 클래스다.
지역 변수처럼 정의된 메서드 내부에서만 사용할 수 있으므로 지역 이너 클래스는 정적 클래스로
지정할 수 없다.
다른 이너 클래스 처럼 아우터 클래스의 멤버를 접근 지정자와 상관없이 사용 가능하다
단, 지역 변수를 사용할 때는 반드시 해당 지역 변수가 final로 선언돼야 한다.
클래스가 정의된 메서드 내부에서만 객체를 생성할 수 있다.
[지역 이너 클래스] [지역 이너 클래스 참조 변수] = new 지역 이너 클래스();
class A{
void abc(){
class B{ //지역 이너 클래스
}
B b = new B(); //지역 이너 클래스 객체 생성
}
}
class A{
int a = 3; //필드
void method() {
int b = 5; //지역 변수
//지역 이너 클래스
class B{
void method2() {
System.out.println(a);
System.out.println(b);
a = 5;
// b = 7 지역 이너 클래스에서 사용 하는 지역 변수는 자동 final선언
}
}
B bb = new B();
bb.method2();
}
}
A a = new A();
a.method2(); // 3, 5
익명 이너 클래스는 말 그대로 '이름을 알 수 없는 이너 클래스'를 의미한다
익명 이너 클래스는 정의된 위치에 따라 분류할 수 있는데
class A{
C c = new B();
void abc(){
c.bcd();
}
class B implements C{
public void bcd(){
System.out.println("인스턴스 이너 클래스");
}
}
}
interface C{
public abstract void bcd();
}
A a = new A();
a.abc(); // 인스턴스 이너 클래스
class A{
C c = new B();
void abc(){
c.bcd(){
System.out.println("익명 이너 클래스");
}
};
void abc(){
c.bcd();
}
}
interface C{
public abstract void bcd();
}
A a = new A();
a.abc(); // 익명 이너 클래스
이너 클래스와 마찬가지로 인터페이스를 클래스 내부에 정의하는 것은 해당 클래스에 의존적인
기능을 수행할 때다.
이너 인터페이스는 사용자 인터페이스의 이벤트 처리에 가장 많이 사용된다.
이너 인터페이스의 특징 중 하나는 정적 이너 인터페이스만 존재할 수 있다는 것이다.
만약 이너 인터페이스 앞에 static 제어자를 생략하면 컴파일러가 자동으로 추가해 준다.
class A{
static interface B{
void bcd();
}
}
이너 인터페이스도 인터페이스므로 자체적으로 객체를 생성할 수 없다.
객체를 생성하기 위해서는 해당 인터페이스를 상속한 자식 클래스를 생성한 후 생성자를 이용해
객체를 생성하거나 익명 이너 클래스를 활용해 객체를 생성해야 한다.
class C implements A.B{
public void bcd();
}
C c = new C();
c.bcd();
A.B a = new A.B(){ //static 이너 클래스일 때와 동일
public void bcd() {}
};
a.bcd();