Super Coding Addict
Ch12. 내부 클래스(1) 본문
< 내부 클래스 >
* 내부 클래스?
- 클래스 내부에 구현한 클래스
- 클래스 내부에서 사용하기 위해 선언하고 구현하는 클래스
* 내부 클래스 유형
- 인스턴스 내부 클래스 / 정적 내부 클래스 / 지역 내부 클래스 / 익명 내부 클래스
- 예제
# InnerTest 클래스
package ch12.innerclass;
class OutClass{
private int num = 10;
private static int sNum = 20;
private InClass inClass;
public OutClass() {
inClass = new InClass();
}
class InClass{
int iNum = 100;
//*static int sInNum = 200; --> InClass가 static이면 상관없겠지만,
//인스턴스 InnerClass는 OuterClass 생성 이후 생성되므로 static 쓸 수 없음
void inTest() {
System.out.println(num);
System.out.println(sNum); //static변수로 OutClass 생성 전 이미 있으므로 쓸 수 있음
}
}
public void usingInner() {
inClass.inTest();
}
static class InStaticClass{ //OuterClass 생성 여부와 상관 없이 쓸 수 있음
int inNum = 100;
static int sInNum = 200;
void inTest() {
System.out.println(inNum);
System.out.println(sInNum);
System.out.println(sNum);
}
static void sTest(){ // cf.인스턴스 InnerClass안에는 static 변수와 메서드 모두 만들 수 없음
//*System.out.println(inNum); --> 클래스 생성 이후 만들어진 변수이므로 static 메서드에선 쓸 수 없음
System.out.println(sInNum);
System.out.println(sNum);
}
}
}
public class InnerTest {
public static void main(String[] args) {
OutClass outClass = new OutClass();
outClass.usingInner();
OutClass.InClass myInClass = outClass.new InClass();
myInClass.inTest();
System.out.println();
OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
sInClass.inTest(); //static메서드가 아니므로 내부에서 static클래스 생성 후 호출해야 함
System.out.println();
OutClass.InStaticClass.sTest();//생성 없이 그대로 쓸 수 있음
}
}
--> InClass와 InStaticClass는 OuterClass인 OutClass의 InnerClass이다
=> 이처럼 컴파일된 class파일이 있는 bin폴더에 가보면 InnerClass가 OuterClass $ 다음에 오고 있음을 알 수 있다
--> InClass는 인스턴스 내부 클래스이므로 Outer클래스를 생성해야 쓸 수 있지만, InStaticClass는 정적(static) 내부 클래스이므로 생성 없이 쓸 수 있다
--> 인스턴스 클래스 안에서는 Static 변수, 메서드 모두 선언 불가하지만 Static 클래스 안에서는 static 변수, 메서드 모두 선언 가능 (run을 하면 메모리에 가장 먼저 올라가는 것이 static이기 때문)
--> main 메서드에서 위에서 선언한 내부 클래스를 어떻게 사용하는 지 따로 뽑아 살펴보자.
public class InnerTest {
public static void main(String[] args) {
OutClass outClass = new OutClass();
outClass.usingInner();
OutClass.InClass myInClass = outClass.new InClass();
myInClass.inTest();
System.out.println();
OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
sInClass.inTest(); //static메서드가 아니므로 내부에서 static클래스 생성 후 호출해야 함
System.out.println();
OutClass.InStaticClass.sTest();//생성 없이 그대로 쓸 수 있음
}
}
OutClass outClass = new OutClass();
outClass.usingInner();
--> Outer클래스인 OutClass 객체를 생성하면 위에 생성자에서 InClass객체를 생성하도록 하였으므로 Inner 클래스인 InClass 객체도 생성됨
--> OutClass객체인 outClass로 바로 InClass의 inTest()메서드를 호출할 수는 없는데, InClass를 private로 선언했기 때문
=> OutClass의 메서드인 usingInner() 메서드로 접근한다 (usingInner()메서드에서 inClass의 inTest()메서드를 호출하고 있음)
OutClass.InClass myInClass = outClass.new InClass();
myInClass.inTest();
--> 다소 생소한 문법이지만, 외부에서 Outer 클래스인 OutClass 내부의 Inner 클래스인 InClass를 OutClass의 참조변수인 outClass를 이용해서 InClass를 생성하는 문법
--> 그러나 이 때 InClass가 private으로 선언되어 있으면 이렇게 접근해 생성은 불가능하다
=> 사실상 내부클래스는 외부에서 쓰려고 만드는 건 아니기 때문에, 내부에서만 쓰면 private으로 선언하는 게 맞음
--> 이렇게 Inner 클래스인 InClass 객체를 생성한 경우, InClass의 inTest() 메서드를 호출할 수 있다
OutClass.InStaticClass.sTest();
--> static클래스인 InStaticClass의 static메서드인 sTest()는 OuterClass인 OutClass의 생성없이도 바로 쓸 수 있다
OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
sInClass.inTest();
--> 그러나 같은 static 내부 클래스 안에 있는 메서드라도, static메서드가 아닌 일반 메서드인 inTest()를 호출하기 위해서는 내부클래스를 생성한 후 호출할 수 있음
'JAVA 문법' 카테고리의 다른 글
Ch10. 자바 기본 클래스 (1) - Object 클래스 (0) | 2021.02.28 |
---|---|
Ch12. 내부 클래스(2) (0) | 2021.02.27 |
Ch11. 컬렉션 프레임워크 (6) (0) | 2021.02.27 |
Ch11. 컬렉션 프레임워크 (5) (0) | 2021.02.25 |
Ch11. 컬렉션 프레임워크 (4) (0) | 2021.02.24 |