Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

Super Coding Addict

Ch12. 내부 클래스(1) 본문

JAVA 문법

Ch12. 내부 클래스(1)

밍응애 2021. 2. 27. 21:58

< 내부 클래스 >

* 내부 클래스?

- 클래스 내부에 구현한 클래스

- 클래스 내부에서 사용하기 위해 선언하고 구현하는 클래스

 

* 내부 클래스 유형

- 인스턴스 내부 클래스 / 정적 내부 클래스 / 지역 내부 클래스 / 익명 내부 클래스

 

- 예제

# 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()를 호출하기 위해서는 내부클래스를 생성한 후 호출할 수 있음