이너클래스란, 클래스 내부에 포함되는 이너 클래스를 말하며, 아래 3가지로 구분됩니다.
객체 내부의 인스턴스 멤버로 존재하는 이너 클래스 입니다.
아우터$이너클래스.class
파일로 생성됩니다.//사용법
아우터클래스 변수명 = new 아우터클래스();
아우터클래스.이너클래스 변수명 = 아우터변수명.new 이너클래스();
//사용예시
class A {
class B {}
}
//-----------------
A a = new A();
A.B b = a.new B();
//이너클래스의 자료형은 아우터.이너클래스명
//아우터 클래스의 참조변수를 이용해 생성해야하기 때문에 a.new B()로 작성합니다.
A a = new A();
A.B b = a.new B();
아웃터클래스.이너클래스
입니다. 이는 해당 이너클래스가 바이트코드로 생성될 때 아우터$이너클래스.class
생성되기 때문입니다.this
이너클래스와 아우터클래스 에서 필드명 또는 메서드명이 중복될 경우 우선적으로 해당 이너클래스 내에 필드, 메서드를 가져옵니다.
이 때 아우터의 필드, 메서드를 가져와야할 경우 this
키워드를 사용할 수 있습니다. 다만, 이너클래스도 클래스이기 때문에 this
를 사용하면 해당 이너클래스 본인 자신을 가르키기 때문에 아우터클래스명.this
로 사용해야합니다.
class A {
int a = 4;
int b = 3;
class B {
int a = 5;
void abc() {
System.out.println(a); //이너클래스 내 a 호출 = 5
System.out.println(this.a); //이너클래스 내 a 호출 = 5
System.out.println(A.this.a); //아우터클래스 내 a 호출 = 4
System.out.println(b); //아우터클래스 내 b 호출
}
}
}
이너 클래스 앞에 static
제어자가가 포함된 이너 클래스 입니다.
아우터$이너클래스.class
파일로 생성됩니다.//사용법
아우터클래스.이너클래스 변수명 = new 아우터클래스.이너클래스();
//사용예시
class A {
class B {}
}
//-----------------
A.B b = new A.B();
//이너클래스의 자료형은 아우터.이너클래스명
클래스의 멤버가 아닌 메서드 내에 정의되는 지역 이너 클래스 입니다.
final
상태여야합니다. (final
아닌 지역변수 접근 시 컴파일러가 강제로 final
상태 추가)아우터$+숫자+이너클래스.class
파일로 생성됩니다. (숫자는 동일한 지역이너클래스 명이 있을 때 +1)//사용법
이너클래스명 변수 = new 이너클래스명();
//사용예시
class A {
void abc() {
class B {}
B b = new B(); //해당 메서드 내에서만 객체 생성 가능
}
}
//-----------------
A.B b = new A.B();
//이너클래스의 자료형은 아우터.이너클래스명
익명 이너 클래스는, '이름을 알 수 없는 이너 클래스'를 말합니다.
//사용법
클래스명 참조변수명 = new 생성자() {
접근제어자 리턴타입 메서드명() {
...;
}
}
//사용예시
interface A {
public abstract void abc();
}
class B {
A a = new A() {
//A인터페이스를 상속받아 추상메서드 abc()를 구현하는 익명 이너 클래스
public void abc() {
...;
}
}
void def() {
a.abc();
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.def(); //b.def() 내에 a.abc() 메서드가 포함되어 있음.
}
}
1. 정적 익명 이너 클래스 존재 불가
: 인스턴스 익명 이너 클래스, 지역 익명 이너 클래스가 있으며, 정적(static) 익명 이너클래스는 존재할 수 없다.
정적(static)의 경우 객체 생성없이 사용 가능해야하는데, 익명 이너클래스의 경우 이름이 없기 때문에 객체 생성 불가
interface A {
public abstract void abc();
}
class B {
A a = new A() { // 인스턴스 익명 이너 클래스
public void abc() {
...;
}
}
void def() {
A aa = new A() { // 지역 익명 이너 클래스
public void abc() {
...;
}
}
}
}
2. 익명 이너 클래스 내 추가 메서드 작성은 가능 / 해당 이너 클래스 밖에서 사용 불가
: 익명 이너 클래스에서도 부모클래스(인터페이스)에서 오버라이딩한 메서드 외 추가 정의 메서드를 작성할 수는 있으나, 익명 이너 클래스의 경우 클래스명이 없어 늘 부모 타입으로만 객체 생성이 가능하여, 추가 작성한 메서드는 익명 이너클래스 내부에서만 사용 가능하다.
interface A {
public abstract void abc();
}
class B {
A a = new A() {
public void abc() { // 부모 인터페이스의 추상메서드 오버라이딩
def(); // 추가 정의 메서드를 내부적으로 호출 가능
}
public void def() { //추가 정의 메서드
...;
}
}
a.abc(); //사용가능
a.def(); //부모 클래스(인터페이스)에 없는 메서드 익명 이너클래스 밖에서 사용불가
}
인터페이스 타입의 매개 변수란,
interface A {
public abstract void abc();
}
class B {
void def(A a) { //인터페이스 A 타입을 매개변수로 받는 메서드
a.abc();
}
}
위와 같은 형태로 매개변수로 받는 A 인터페이스를 구현한 자식 클래스의 객체가 매개변수로 전달이 필요한 메서드를 말합니다.
이 매개변수를 전달하는 방법으로는 4가지 형태가 있습니다.
- 방법 ① : A 인터페이스를 구현한 구현 클래스 작성 후 각 각 객체 생성하여 전달
class C implements A {
public void abc() {
...;
}
}
B b1 = new B();
A ac = new C(); //B.def()의 매개 변수가 A타입으로 정의되어있기 때문에 A타입으로 C객체 생성 필요
bb.def(ac);
- 방법 ② : A 인터페이스를 구현한 구현 클래스 작성 후 new 생성자 이용
class C implements A {
public void abc() {
...;
}
}
B b2 = new B();
b2.def(new C());
- 방법 ③ : A 인터페이스를 구현한 익명 이너클래스 작성하여 객체 생성 후 전달
B b3 = new B();
A a1 = new A() {
public void abc() {
...;
}
}
b3.def(a1);
- 방법 ④ : 매개변수로 바로 익명 이너 클래스 작성하여 전달
B b4 = new B();
b4.def(new A() {
public void abc() {
...;
}
});
방법 ④의 경우 이벤트 처리 시 많이 이용된다고 합니다.
인터페이스를 클래스 내부에 정의하는 것을 말합니다. 해당 클래스 내에서 의존적인 기능을 수행할 때 사용할 수 있습니다. (주로 이벤트 처리 시 이용 = '리스너')
class A {
static interface B {
public abstract abc();
}
}
1. 정적 이너 인터페이스만 존재할 수 있습니다.
모든 이너 인터페이스는 정적(static) 인터페이스만 존재할 수 있으며, static
제어자 미입력시 컴파일러가 자동으로 추가해줍니다.
2. 이너 인터페이스도 자체적으로 객체를 생성할 수 있습니다.
이너 인터페이스도 인터페이스이기 때문에 자체적으로 객체를 생성할 수 없으며, 구현 클래스를 작성 후 구현 클래스의 생성자로 객체 생성 또는 익명 이너 클래스를 활용하여 객체를 생성해줄 수 있습니다.
3. 이너 인터페이스의 객체 타입은 아웃터클래스명.이너인터페이스명
입니다.
이너 인터페이스의 경우 아웃터 클래스 내부에 위치해 있기 때문에 이너클래스와 유사하게 타입이 아웃터클래스명.이너인터페이스명
이 됩니다.
class A {
static interface B {
public abstract abc();
}
}
//구현 클래스 작성
class C implements A.B {
//abc 메서드 구현
}
C c = new C();
c.abc();
//익명 이너 클래스 작성
A.B ab = new A.B() {
//abc 메서드 구현
}
ab.abc();
Do it! 진짜 개발자가 되는 Java 프로그램 입분서 자바 완전 정복 - 김동형
위 책을 공부하며 작성하고 있습니다!