Java & Kotlin

[Java 기능] 중첩 클래스 (1)

Sue 2022. 2. 13. 15:33

내부 클래스(Inner class)

  • 클래스 내부에 선언한 클래스로 이 클래스를 감싸고 있는 외부 클래스(outer class)와 밀접한 관련이 있는 경우 많음
  • 다른 외부 클래스에서 사용할 일이 거의 없는 경우에 내부 클래스로 선언해서 사용 
  • 중첩 클래스라고도 함
  • 외부 클래스(outer class)의 private 변수 사용 가능
  • 종류 : 인스턴스 내부 클래스, 정적(static) 내부 클래스, 지역(local) 내부 클래스, 익명 내부 클래스
  • 익명 내부 클래스가 가장 많이 사용됨

 

인스턴스 내부 클래스

  • 내부적으로 사용할 클래스를 선언 (private으로 선언하는 것을 권장)
  • 외부 클래스가 생성된 후 생성됨
  • private이 아닌 내부 클래스는 다른 외부 클래스에서 생성할 수 있음
OutClass outClass = new OutClass();
OutClass.InClass inClass = outClass.new InClass();	// 다른 외부 클래스에서 내부 클래스 생성

 

InnerTest.java
  • 인스턴스 내부 클래스에서는 static 변수를 사용할 수 없음
  • 인스턴스 내부 클래스는 외부 클래스가 생성된 후 생성됨
  • static 변수는 외부 클래스의 생성과 상관없이 사용하는 변수
  • static 변수가 생성되는 시점에 인스턴스 내부 클래스가 존재하지 않을 수 있음
package ch01;

class OutClass{	// 외부 클래스
	
	private int num = 10;
	private static int sNum = 20;
	private InClass inClass;
	
	public OutClass() {	// 외부 클래스 생성자에서 내부 클래스 생성
		inClass = new InClass();
	}
	
	private class InClass{	// 내부 클래스
		
		int iNum = 100;
        // 	static int sNum = 200; 오류
		
		void inTest() {
			
			System.out.println("OutClass num = " + num + "(외부 클래스의 인스턴스 변수)");
			System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 static 변수)");
			System.out.println("InClass iNum = " + iNum + "(내부 클래스의 인스턴스 변수)");
			
		}
	}
	
	public void usingClass() {
		inClass.inTest();
	}
}

public class InnerTest {

	public static void main(String[] args) {
		
		OutClass outClass = new OutClass();
		outClass.usingClass();
		
	}

}

 

수행 결과
OutClass num = 10(외부 클래스의 인스턴스 변수)
OutClass sNum = 20(외부 클래스의 static 변수)
InClass iNum = 100(내부 클래스의 인스턴스 변수)

 

정적 내부 클래스

  • 외부 클래스의 생성과 무관하게 사용 가능
  • 정적 변수와 정적 메서드 사용 가능

 

InStaticClass
  • 정적 내부 클래스의 일반 메서드에서는 외부 클래스의 인스턴스 변수를 사용할 수 없음
  • 정적 내부 클래스는 외부 클래스의 생성과 상관없이 사용 가능
  • 외부 인스턴스 변수는 외부 클래스가 생성된 후에 사용할 수 있으므로 변수가 생성되지 않았을 때 메서드가 호출될 수 있음
  • 정적 메서드에서는 정적 변수만 사용 가능
static class InStaticClass {

    int iNum = 100;
    static int sInNum = 200;

    void inTest() {

//	System.out.println("OutClass num = " + num + "(외부 클래스의 인스턴스 변수)"); 오류
        System.out.println("InClass iNum = " + iNum + "(내부 클래스의 인스턴스 변수)");
        System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 static 변수)");
        System.out.println("OutClass sInNum = " + sInNum + "(내부 클래스의 static 변수)");

    }

    static void sTest() {

//	System.out.println("InClass iNum = " + iNum + "(내부 클래스의 인스턴스 변수)"); 오류
        System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 static 변수)");
        System.out.println("OutClass sInNum = " + sInNum + "(내부 클래스의 static 변수)");
    }

}

 

InnerTest
public class InnerTest {

	public static void main(String[] args) {
				
		OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
		sInClass.inTest();	// static 클래스의 일반 메서드 호출
		
		System.out.println();
		
		OutClass.InStaticClass.sTest();	// static 클래스의 static 메서드 호출
		
	}

}

 

수행 결과
InClass iNum = 100(내부 클래스의 인스턴스 변수)
OutClass sNum = 20(외부 클래스의 static 변수)
OutClass sInNum = 200(내부 클래스의 static 변수)

OutClass sNum = 20(외부 클래스의 static 변수)
OutClass sInNum = 200(내부 클래스의 static 변수)