시소당
1. Inner Class
말 그대로 클래스안에 사용하는 클래스입니다.
1-1 왜 Inner Class를 사용하는가?
자바 튜토리얼에 따르면, "Inner Class는 바깥에서는 부를 수 없
다(예외는 항상있는 법). 고로 클래스를 패키지 처럼, 혹은 패키
지안에서 좀 더 구조적으로 관리하기가 쉽다"라고 설명을 하더군
요. 또 한 가지 더 설명을 해 놓았는데 별로 맘에 내키지 않는
부분이더군요. 그 외로 이벤트를 처리할 때 괜찮은 것 같더군요.
그리구 뭐 내부 클래스를 참조 할 때 같은 클래스내에 있고 무엇
보다 객체와 가까이에 있어서 이해가 쉽고, 관리가 편하다는 데
글쎄요, 이건 개인의 취향에 따라 달라지겠더군요.
1-2 어떻게 사용하는가?
Inner Class에는 Adapter Class, Local Class, Anonymous Class
가 있습니다.
- 바로 위에서 말했죠, 클래스 밖에서는 참조가 안된다구요. 예외
도 있다구 말씀드렸죠. 그 예외는 직접 해결하세요. 전 정력이 딸
려서리....^^;
- static 메쏘드안에서 Inner Class를 참조할 때는 Inner Class를
static으로 만들어 주든가 Top-Level-Class 의 객체를 생성해서 참
조해야합니다.
거꾸로 설명을하는 느낌입니다만, 익명 클래스 부터 먼저 설명을 하겠
습니다. 여러분께서는 어댑터 클래스 부터 보고 나서 로컬 클래스, 익
명클래스를 보셔도 좋겠습니다.
1-2-1 Anonymous Class (익명클래스?)
말 그대로 이름이 없는 클래스입니다. 그러니 생성자(Constructor)
는 당연히 없겠죠.
예제 1-2-1-1)
public class SIC {
public static void main (String [] args) {
new SIC().prove().display(); // 1
}
public SIC_IF prove() { // 2
return new SIC_IF () { // 3
public void display() { // 5
System.out.println("Did you get it?");
}
};
}
public interface SIC_IF { // 4
void display();
}
}
첫번째 예제가 조금 쉬운가요? 아니면 좀 어려운가요?
앞으로 이정도 난이도(?)의 예제를 만들어 가겠습니다.
그나 저나, 예제에 대한 설명을 해드려야겠네요.
주석에 번호를 매겨놓았죠? 그 순서대로 설명할께요.
주석1 : 뭐 여기서는 별로 이상한 게 없죠. 늘 보던 코드일 테니깐
요.
none static 메쏘드인 prove()를 static 메쏘드인 main()에서
호출할 수 없다는 것은 다 아실거구, 그래서 new SIC()하고 객
체를 생성해서 참조하죠. 그런데, display()가 약간 신경쓰이
죠.
주석 2 : prove()를 함수를 보세요. SIC_IF 라는인터페이스 타입을
리턴하죠? 이것은 주석4에 나오는 인터페이스를 사용한 것입니
다. 그럼 주석 4를 한번 볼까요? 인터페이스를 SIC 클래스 안
에서 선언했죠. JDK1.1에서부터는 이게 가능합니다.
이 경우의 인터페이스도 하나의 내부 클래스라고 봐야겠지요.
주석 3 : SIC_IF 인터페이스형 Anonymous 클래스의 객체를 리턴하고
있습니다. 왜 Anonymous 형 클래스 객체를 리턴할 때는 인터페이
스를 이용하는가 하면 익명 클래스는 클래스 이름이 없기때문에
객체를 생성한 뒤 그 객체 참조 방법을 쉽게 하기 위해서입니다.
주석 5 : 이 메쏘드는 인터페이스에서 정의된것으로 당연히 구현 해
주어야합니다.
그외 : 익명클래스는 로컬클래스를 정의해서 리턴하는 것과 똑
같은 결과를 가집니다. 다만 좀 더 간단하게 표현한거죠.
익명클래스는 알아보기(이해가기) 쉽게 간단하게 작성하라는 말
이있구 또, 잘만 쓰이면 관리하기가 더 쉽다 등등... 잔소리가
많은데요, 그것도 다 사용하는 사람나름이죠. 다만 프로그래밍
방식에도 관례가 있고, 예의(?)가 있다는군요.
우와, 이거 생각보다 설명하기가 쉽지않은데요. ^^;
게다가 영문 윈95에서 한글을 쓰려니 환장하겠네요. 한글을 썼다
영어를 썼다 바꿔하기가 상당히 어렵네요.
익명 클래스에 대해 간단한 예제를 하나 더 들고 넘어가겠습니다.
아차, 깜박하고 그냥 넘어갈 뻔했네요, 익명클래스에는 ()과 ;를
꼭 붙여 주셔야합니다.
예제 1-2-1-2)
public class SIC {
public static void main (String [] args) {
gimmeMsg("Bad Codes").display();
}
public static t_interface gimmeMsg (final String m) { // 1
return new t_interface () {
public void display() {
System.out.println("Message : "+m);
}
};
}
private static interface t_interface {
void display();
}
}
아주 간단한 예제이네요. 주석 1 을 한번보세요. 파라메타에 final이라
고 선언해주었습니다. 이와같이 지역변수나 파라미터가 Inner Class에서
참조되는 경우에는 final로 선언해주어야합니다. 왜 final 로 선언해 줘
야하는 고 하니 내부클래스의 메쏘드에서 지역변수나 파라메타를 사용하
기 위해서는 컴파일러가 내부클래스에서 읽을 수 있도록 그 내부클래스에
그 지역변수의 값을 복사를 합니다. 이때 혹시 생길지 모르는 동기화 문
제 때문에 final을 사용한다는군요.
1-2-2 Adapter Class
내부 클래스라 함은 이 어댑터 클래스를 두고하는 말 같습니다.
사용하기도 아주쉽구요, 아무래도 가장 많이 쓰일 내부클래스일 것 같
군요.
우선 간단한 예제 부터 보죠.
예제 1-2-2-1)
public class SIC {
public static void main (String [] args) {
new IC().display();
}
}
class IC {
void display() {
System.out.println("IC");
}
}
위에 흔히 볼 수 있는 두개의 클래스가 있습니다. 하나로 합쳐볼까요?
재미있을겁니다.
예제 1-2-2-2)
public class SIC {
public static void main (String [] args) {
new IC().display();
}
static class IC {
void display() {
System.out.println("IC");
}
}
}
무엇이 달라졌습니까? IC 클래스가 SIC Class 안으로 들어가고
static 으로 바뀌었죠.
이렇게도 해보세요. 내부 클래스에서 static을 없애고 메인 메쏘드 위
에서 내부 클래스의 객체 생성을 해보세요.
예제 1-2-2-3)
public class SIC {
IC ic = new IC();
public static void main (String [] args) {
new SIC().ic.display();
}
class IC {
void display() {
System.out.println("IC");
}
}
}
위의 예제에서 IC 내부클래스의 객체를 생성할 때 statci 키워드를 준다
면 static 메쏘드내에서 바로 참조할 수 있습니다. 단, 그 Inner Class
에도 static 키워드를 써 줘야 컴파일이 되더군요. 그럼 뭔가 좀 이상한
느낌(?)이 들죠? 아래의 예제는 각각의 참조 경우를 보여줍니다. 맘에
드는 것을 골라잡아서(?) 사용하시면 되겠습니다.
예제 1-2-2-4)
public class IC_Lec {
S s = new S();
static S ss = new S();
NS ns = new NS();
//static NS nss = new NS(); Error
public static void main (String [] args) {
new S().display();
//s.display(); Error
new IC_Lec().s.display();
ss.display();
//ns.display(); Error
new IC_Lec().ns.display();
}
static class S {
void display() {
System.out.println("I am a static Inner Class.");
}
}
class NS {
void display() {
System.out.println("I am a none static Inner Class.");
}
}
}
어댑터 클래를 이정도에서 끝내겠습니다.
1-2-3 Local Class(로컬클래스)
로컬 클래스라 하는 것은 블럭(메쏘드)안에서 정의되고 사용되는 내부 클
래스입니다. 그래서 블럭 밖으로 밖으로 알리기(객체를 리턴하기)위해서
는 익명 클래스처럼 인터페이스를 사용합니다.
블럭내에서 내부클래스를 정의하고 리턴하는 함수를 만들어 보고 내부
클래스에 대해서 설명을 마치겠습니다.
예제 1-2-3-1)
public class SIC {
public static void main (String [] args) {
SIC sic = new SIC();
t_interface alo = sic.gimmeALocalObjet("All right by me");
alo.display();
System.out.println(alo.type);
}
t_interface gimmeALocalObjet(final String s) { // 1
class ALocalClass implements t_interface { // 2
public void display() { // 3
System.out.println(s);
}
}
t_interface alocalclass = new ALocalClass(); // 5
return alocalclass; // 4
}
interface t_interface {
String type="The type of this object is t_interface";
void display();
}
}
원문 : http://database.sarang.net/study/java/doc-1/inner.html