class ClassName{
class NestedClassName{ //중첩 클래스
}
}
class ClassName{
interface NestedInterfaceName{
}
}
구분 | 분류 | 설명 |
---|---|---|
멤버 클래스 | 인스턴스 멤버 클래스 | 상위 객체를 생성해야만 사용할 수 있는 하위 중첩 클래스 |
멤버 클래스 | 정적 멤버 클래스 | 상위 객체로 바로 접근할 수 있는 하위 중첩 클래스 |
로컬 클래스 | 메소드 실행할 때만 사용할 수 있는 하위 중첩 클래스 |
class A{
//인스턴스 멤버 클래스
class B{
B(){ } // 생성자
int field1; //인스턴스 필드
//static int field2; -> 정적 필드는 선언할 수 없음
void method1() { } //인스턴스 메소드
//static void method2 { } -> 정적 메소드는 선언할 수 없음
}
}
A a = new A();
A.B = a.new B();
b.field1 = 3;
b.method1();
class A{
//정적 멤버 클래스
class C{
C(){ } // 생성자
int field1; //인스턴스 필드
static int field2; //정적 필드
void method1() { } //인스턴스 메소드
static void method2 { } //정적 메소드
}
}
A.C c = new A.C();
c.field1 = 3; //인스턴스 필드 사용
c.method1(); //인스턴스 메소드 호출
A.C.field2 = 3; //정적 필드 사용
A.C.method2(); //정적 메소드 호출
void method(){
//로컬 클래스
class D{
D(){ } //생성자
int field1; //인스턴스 필드
//static int field2; //정적필드는 사용할 수 없음
void method1() { } //인스턴스 메소드
//static void method2() { } //정적 메소드는 사용할 수 없음
}
D d = new D();
d.field1 = 3;
d.method1();
}
→ 로컬 클래스는 메소드가 실행될 때 메소드 내에서 객체를 생성하고 사용해야한다. 주로 비동기 처리를 위해 스레드 객체를 만들 때 사용하게 된다.
public class A{
//인스턴스 필드
B field1 = new B(); //가능
C field2 = new C(); //가능
//인스턴스 메소드
void method1() {
B var1 = new B(); //가능
C var2 = new C(); //가능
}
//정적 필드 초기화
//static B field3 = new B(); //불가능
static C field4 = new C(); //가능
//정적 메소드
static void method2() {
//B var1 = new B(); //불가능
C var2 = new C();
}
//인스턴스 멤버 클래스
class B{}
//정적 멤버 클래스
static class C {}
}
결론적으로 로컬 클래스에서 사용 가능한 것은 final로 선언된 매개 변수와 로컬 변수뿐이라는 것이다.
void outMethod(final int arg1, int arg2){
final int var1 = 1;
int var2 = 2;
class LocalClass {
void method(){
int result = arg1 + arg2 + var1 + var2;
}
}
}
class LocalClass{
int arg2 = 매개값;
int var2 = 2;
//필드로 복사
void method(){
int arg1 = 매개값;
int var1 = 1;
//로컬 변수로 복사
int result = arg1 + arg2 + var1 + var2;
}
}
💡 로컬 클래스의 내부 복사 위치에 신경 쓸 필요 없이 로컬 클래스에서 사용된 매개 변수와 로컬 변수는 모두 final 특성을 갖는다.
바깥클래스.this.필드;
바깥클래스.this.메소드();
class A{
interface I {
void method();
}
}
//-> 중첩 인터페이스
public class Button{
OnClickListener listener; //인터페이스 타입 필드
void setOnClickListener(OnClickListener listener){
this.listener = listener;
}
void touch(){
listener.onClick();
}//구현 객체의 onClick() 메소드 호출
interface OnClickListener{
void onClick();
}
} //중첩 인터페이스
부모클래스 [필드||변수] = new 부모클래스(매개값, ...){
//필드
//메소드
};
class A{
void method(){
Parent localVar = new Parent(){ //로컬변수 선언
int childField;
void childMethod();
@Override
void parentMethod(){} //Parent의 메소드를 오버라이딩
}; //익명 객체라면 끝에 세미콜론이 와야한다.
}
}
인터페이스 [필드||변수] = new 인터페이스(){
//인터페이스에 선언된 추상 메소드의 실체 메소드 선언
//필드
//메소드
};
초기값으로 익명 구현 객체 사용
class A{
RemoteControl field = new RemoteControl() {
@Override //RemoteControl 인터페이스의 추상 메소드에 대한 실체 메소드
void turnOn(){}
};
}
로컬 변수 초기값으로 익명 구현 객체 사용
class method{
RemoteControl localVar = new RemoteControl() {
@Override //RemoteControl 인터페이스의 추상 메소드에 대한 실체 메소드
void turnOn(){}
};
}
매개 변수가 인터페이스 타입일 경우
class A{
void method1(RemoteControl rc){ }
void method2(){
method1(
new RemoteControl(){ //method1()의 매개값으로 익명 구현 객체를 대입
@Override
void turnOn(){ }
}
);
}
}