자바 4대 중첩 클래스
1. 중첩 클래스 (Inner Class)
□ 정의
- 하나의 클래스 내부에 또 다른 클래스가 내포되어 있는 상태. (클래스 관리의 효율을 높임.)
□ 특징
- 중첩되는 클래스는 하나 이상 가능.
- Outer 클래스 멤버를 Inner 클래스에서 사용 가능.
- Outer 클래스에서 Inner 클래스 멤버 사용 불가능. (사용하고 싶으면 객체를 직접 발생 시켜야 함.)
- 일반 중첩 클래스 내부에서는 static과 관련된 멤버를 선언할 수 없음.
□ 형식
class Outer { 내용부; class Inner { 내용부; } } |
□ 중첩 클래스 객체 생성
Outer 객체1 = new Outer(); // Outer 클래스 객체 생성. Outer.Inner 객체2 = 객체1.new Inner(); // Inner 클래스 객체 생성. |
□ 생성된 클래스 파일 형식
- Inner 클래스는 '$'라는 기호로 표시.
Outer_클래스명.class Outer_클래스명$Inner_클래스명.class // ex> Outer$Inner.class |
□ 예제
■ Inner 클래스에서 Outer 클래스 멤버 접근 예제
/* Exam01 class */ public class Exam01 { private int x = 100; class Inner { private int y = 200; public void display() { System.out.println("x : " + x); System.out.println("y : " + y); } } } |
/* Exam02 class */ public class Exam02 { public static void main(String[] args) { Exam01 outer = new Exam01(); Exam01.Inner inner = outer.new Inner(); inner.display(); } } |
/* output */ x : 100 y : 200 |
■ Outer 클래스에서 Inner 클래스 멤버 접근 예제
/* Exam03 class */ public class Exam03 { private int x = 100; public void display() { System.out.println("x : " + x); // System.out.println("y : " + y); // compile error. Inner in = new Inner(); // 원형 : Exam03.Inner in = this.new Inner(); System.out.println("y : " + in.y); } class Inner { private int y = 200; } } |
/* Exam04 class */ public class Exam04 { public static void main(String[] args) { Exam03 out = new Exam03(); out.display(); } } |
/* output */ x : 100 y : 200 |
/* Exam05 class */ public class Exam05 { private static int x = 100; class Inner { private int x = 200; public void display() { System.out.println("x1 : " + Exam05.x); System.out.println("x2 : " + this.x); } } } |
/* Exam06 class */ public class Exam06 { public static void main(String[] args) { Exam05 out = new Exam05(); Exam05.Inner in = out.new Inner(); in.display(); } } |
/* output */ x1 : 100 x2 : 200 |
2. 정적 중첩 클래스 (Static Inner Class)
□ 정의
- 중첩 클래스 내부에서 static과 관련된 멤버를 선언할 수 있는 클래스.
□ 특징
- 클래스의 이름 앞에 static 예약어가 붙음.
- static의 특성상 객체를 독립적으로 만들 수 있음.
- static 멤버를 선언할 수도 있고 static 메서드도 만들어 사용할 수 있음.
- Outer 클래스의 static 멤버만 Inner에서 사용할 수 있음.
□ 형식
class Outer { 내용부; static class Inner { 내용부; } } |
□ 객체 생성 방법
Outer.Inner 객체 = new Outer.Inner(); |
- Outer 클래스의 객체가 없어도 Inner 클래스의 객체 생성 가능.
□ 예제
■ Outer 클래스의 static 멤버 Inner 클래스에서 사용 예제
/* Exam07 class */ public class Exam07 { private int x = 100; private static int z = 300; static class Inner { private int y = 200; public void display() { // System.out.println("x : " + x); // compile error. (일반 멤버는 사용할 수 없음.) System.out.println("z : " + z); System.out.println("y : " + y); } } } |
/* Exam08 class */ public class Exam08 { public static void main(String[] args) { Exam07.Inner in = new Exam07.Inner(); in.display(); } } |
/* output */ z : 300 y : 200 |
3. 지역 중첩 클래스 (Local Inner Class)
□ 정의
- 특정 메서드에 한정적인 용도로 사용하는 클래스.
□ 특징
- 접근 제한자와 지정 예약어를 사용할 수 없는 형태.
- 일반 중첩 클래스의 형태와 유사하기 때문에 static 멤버를 선언하지 못함.
- 객체 생성은 외부에서 할 수 없음.
□ 형식
class Outer { 내용부; method() { 내용부; class Inner { 내용부; } } } |
□ 생성된 클래스 파일 형식
- Inner 클래스는 '$'라는 기호로 표시.
Outer_클래스명.class Outer_클래스명$숫자Inner_클래스명.class // ex> Outer$1Inner.class |
□ 예제
■ 메서드 안에서 Inner 클래스 사용 예제
/* Exam09 class */ public class Exam09 { public static void main(String[] args) { int x = 100; class Inner { int y = 200; } Inner in = new Inner(); System.out.println("x : " + x); System.out.println("y : " + in.y); } } |
/* output */ x : 100 y : 200 |
■ 메서드 안 Inner 클래스가 메서드의 멤버 사용 예제
/* Exam10 class */ public class Exam10 { public static void main(String[] args) { final int x = 300; // final로 선언해야 Inner 클래스에서 사용 가능. class Inner { int y = 400; public void display() { System.out.println("x : " + x); System.out.println("y : " + y); } } Inner in = new Inner(); in.display(); } } |
/* output */ x : 300 y : 400 |
4. 익명 중첩 클래스 (Anonymous Inner Class)
□ 정의
- 지역 중첩 클래스의 변형된 형태.
- 기존 클래스의 특정 메서드를 오버라이딩하여 원하는 형태로 재정의하여 사용회는 방식.
□ 특징
- class 예약어와 클래스명을 가지지 않고 단지 instance의 생성과 내용부의 정의만 가짐.
- 여기에 사용되는 중첩 클래스는 이미 기존에 존재하는 클래스이어함.
- 내부 클래스는 생성자를 작성할 수 없음. (생성자를 작성하게 되면 컴파일 에러 발생.)
- 외부 멤버 중 final만 포함.
□ 형식
class Inner { 내용부; } class Outer { 내용부; method() { 내용부; new Inner() { 내용부; }; } } |
□ 생성된 클래스 파일 형식
- 클래스 이름이 없기 때문에 숫자로 그 클래스를 표시.
Outer_클래스명$숫자.class // ex> Outer$2.class |
□ 예제
/* Exam11 class */ public class Exam11 { int y = 200; public Exam11() { this.display(); } public void display() { System.out.println("Exam11 class"); } } |
/* Exam12 class */ public class Exam12 { public static void main(String[] args) { final int x = 100; // final로 선언해야 Inner 클래스에서 사용 가능. new Exam11() { public void display() { // overriding System.out.println("Default 생성자"); System.out.println("x : " + x); System.out.println("y : " + y); } }; } } |
/* output */ Default 생성자 x : 100 y : 200 |
/* Exam13 class */ public class Exam13 { public void aaa() { System.out.println("aaa"); } public void bbb() { System.out.println("bbb"); } public void ccc() { System.out.println("ccc"); } } |
/* Exam14 class */ public class Exam14 { public static void main(String[] args) { Exam13 in = new Exam13() { public void bbb() { System.out.println("DDD"); ddd(); // 익명 중첩 클래스 안에서 생성한 메소드 사용 가능. } public void ddd() { System.out.println("ddd"); } }; in.aaa(); in.bbb(); in.ccc(); // in.ddd(); // 익명 중첩 클래스 안에서 생성한 메소드 사용 불가능. } } |
/* output */ aaa DDD ddd ccc |
한방 테스트 코드
public class NestedClassTest {
private int aa = 20;
static private int bb = 30;
public NestedClassTest(){}
//정적 중첩 클래스
static class StaticInnerClass{
public int a = 10;
static public int b = 10;
public StaticInnerClass(){}
public int getAA(){ //Static 변수만 접근 가능
return bb;
}
}
//중첩 클래스
class InnerClass{
public int a = 10;
//static public int b = 10; //Static 선언 안됨
public InnerClass(){}
public int getAA(){
return aa;
}
}
//지역 중첩 클래스를 위한 메소드
void methodLocalInnerClass(){
class LocalInnerClass{
int a = 10;
//static int b = 20; //Static선언 안됨
}
System.out.println("Local Inner Class: "+new LocalInnerClass().a);
}
//익명 중첩 클래스를 위한 메소드
void methodAnonymousInnerClass(){
System.out.println("Anonymous Inner Class: ");
}
public static void main(String[] args) {
NestedClassTest outer = new NestedClassTest(){
//오버라이딩할때 aaa()를 참조
void methodAnonymousInnerClass(){
System.out.println("Anonymous Inner Class: "+aaa());
}
int aaa(){
return 77;
}
};
//중첩클래스들 선언 방식
StaticInnerClass sinner = new NestedClassTest.StaticInnerClass();
System.out.println("Static Inner Class: "+sinner.a);
NestedClassTest.InnerClass inner = outer.new InnerClass();
System.out.println("Inner Class: "+inner.a);
outer.methodLocalInnerClass();
outer.methodAnonymousInnerClass();
//outer.aaa(); //사용불가
}
}
'Language > Java' 카테고리의 다른 글
Java Garbage Collection (0) | 2014.02.27 |
---|---|
Interface vs Abstract (0) | 2014.02.27 |
JAVA 접근 제한자 (public, private, protected, default) (1) | 2014.02.27 |
Java Reflection 개념 및 사용법 (4) | 2014.02.27 |
JAVA ThreadLocal (0) | 2014.02.27 |