본문 바로가기

JAVA/JAVA 이론

[JAVA 이론] 내부 클래스(Inner Class)

[JAVA 기초]

1. 클래스와 객체

2. 필드(Field)와 메서드(method)

3. 생성자(Constructor)

4. 내부 클래스(Inner Class)


개요

클래스 안의 클래스를 의미하는 내부 클래스에 대해 알아보겠습니다.


학습 목표

  • 내부 클래스의 기본 개념과 장점에 대해 이해한다.
  • 선언 위치에 따른 내부 클래스의 종류와 특징애 대해 이해한다.
  • 내부 클래스의 종류에 따른 유효 범위와 접근성을 이해한다.

내부 클래스

내부 클래스(Inner Class)는 클래스 내에 선언된 클래스로, 외부 클래스와 내부 클래스가 서로 연관된 있을 때 사용됩니다.

내부 클래스를 사용하면 외부 클래스의 멤버들에 쉽게 접근할 수 있고, 코드의 복잡성을 줄일 수 있습니다.

아래의 예제 코드를 살펴보도록 하겠습니다.

Class Outer {	// 외부 클래스
	class Inner {
    	// 내부 클래스
    }
    
    static class StaticInner{
    	// 정적 내부 클래스
    }
    
    void run() {
    	class LocalInner {
        	// 지역 내부 클래스
        }
    }
}

위의 코드 예제를 보면 외부 클래스와 그안에 포함될 수 있는 세 가지의 내부 클래스의 종류를 확인할 수 있습니다.

 

내부 클래스는 외부 클래스 내에 선언된다는 점을 제외하면 일반 클래스와 차이점이 없습니다.

단지 외부 클래스와 내부 클래스가 서로 연관되어 있을 때 사용의 편의성을 고려하여 만들어진 문법 요소입니다.

위의 세 가지 내부 클래스는 변수가 선언 위치에 따라 인스턴스 변수, 클래스 변수, 지역 변수로 구분되는 것과 유사하게 

선언 위치에 따라 구분될 수 있고,유효 범위(scope)와 특성이 변수와 매우 유사합니다.

아래 표를 통해 선언 위치에 따른 내부 클래스의 구분을 살펴봅시다.

 

종 류 선언 위치 사용 가능한 변수
인스턴스 내부 클래스(instance inner class) 외부 클래스의 멤버 변수 선언위치에 선언(멤버 내부 클래스) 외부 인스턴스 변수,
외부 전역 변수
정적 내부 클래스(static inner class) 외부 클래스의 멤버 변수 선언위치에 선언(멤버 내부 클래스) 외부 전역 변수
지역 내부 클래스(local inner class) 외부 클래스의 메서드나 초기화블럭 안에 선언 외부 인스턴스 변수,
외부 전역 변수
익명 내부 클래스(anonymous inner class) 클래스의 선언과 객체의 생성을 동시에 하는 일회용
익명 클래스
외부 인스턴스 변수,
외부 전역 변수

멤버 내부 클래스

인스턴스 내부 클래스

인스턴스 내부 클래스는 객체 내부에 멤버 형태로 존재하며, 외부 클래스의 모든 접근 지정자의 멤버에 접근할 수 있습니다.

아래의 코드 예제를 통해 한번 확인해봅시다.

class Outer{	//외부 클래스
	private int num = 1;		//외부 클래스 인스턴스 변수
    private static int sNum =2;	//외부 클래스 정적 변수
    
    private InClass inclass;	//내부 클래스 자료형 변수 선언
    
    public Outer() {
    	inClass = new InClass(); 	//외부 클래스 생성자
    }
    class InClass {		//인스턴스 내부 클래스
    	int inNum = 10;	//내부 클래스의 인스턴스 변수
        
        void Test() {	//내부 클래스의 메서드
        	System.out.println("Outer num = " + num + "(외부 클래스의 인스턴스 변수)");
            System.out.println("Outer sNum + " + Snum + "(외부 클래스의 정적 변수)");
        }
    }
    public void testClass() {	//외부 클래스의 메서드
    	inClass.Test();	//내부 클래스의 Test 메서드 호출
    }
}
public class Main {
	public static void main(String[] args){
    	Outer outer = new Outer();	
        System.out.println("외부 클래스 사용하여 내부 클래스 기능 호출");
        outer.testClass();
    }
}

// 출력 결과

외부 클래스 사용하여 내부 클래스 기능 호출
Outer num = 1(외부 클래스의 인스턴스 변수)
Outer sNum = 2(외부 클래스의 정적 변수)

위의 코드 예제를 확인해 보면 인스턴스 내부 클래스는 외부 클래스의 내부에 위치해 있으며 private 접근 제어자를 사용하고 있음에도 내부에서 외부 클래스의 인스턴스 변수와 정적 변수에 각각 접근하여 해당 값을 사용하고 있습니다.

따라서 클래스의 생성과 상관없이 사용할 수 있는 정적 변수와 정적 메서드는 인스턴스 내부 클래스에서 선언할 수 없습니다.


정적 내부 클래스

인스턴스 내부 클래스를 확인하며 우리는 내부 클래스가 외부 클래스의 존재에 의존하고 있다는 사실을 알 수 있었습니다.

내부 클래스가 외부 클래스의 존재와 무관하게 정적 변수를 사용할 수 있게 하려면 어떻게 해야 할까요?

 

이 경우 사용하는 것이 정적 내부 클래스입니다. 정적 내부 클래스는 인스턴스 내부 클래스와 동일하게 클래스의 멤버 변수 위치에 정의하지만, static 키워드를 사용한다는 점에서 차이가 있다고 할 수 있습니다.

아래의 코드 예제를 보고 확인해 봅시다.

Class Outer {	 //외부 클래스
	private int num = 3;	// 외부 클래스의 인스턴스 변수
    private static int sNum =4; // 외부 클래스의 정적 변수
    
    void getPrint() {
    	System.out.println("인스턴스 메서드");
    }
    static void getPrintStatic(){
    	System.out.println("스태틱 메서드");
    }
    
    static class StaticInClass { //정적 내부 클래스
    	void test(){
        	System.out.println("Outer sNum " + sNum + "(외부 클래스의 정적 변수)");
            getPrintStatic();
        }
    }
}

public class Main {
	public static void main(String[] args){
    	Outer.StaticInClass a = new Outer.StaticInClass(); // 정적 이너 클래스의 객체 생성
        a.test();
    }
}

//출력값
Outer sNum = 4(외부 클래스의 정적 변수)
스태틱 메서드

지역 내부 클래스

지역 내부 클래스는 클래스의 멤버가 아닌 메서드 내에서 정의되는 클래스입니다.

예제 코드를 보고 확인해 봅니다.

Class Outer {
	int num = 5;
    void test() {
    	int num2 = 6;
        class LocalInClass {
        	void getPrint() {
            	System.out.println(num);
                System.out.println(num2);
            }
        }
        LocalInClass localInClass = new LocalInClass();
        localInClass.getPrint();
    }
}
public class main{
	public static void main(String[] args){
    	Outer outer = new Outer();
        outer.test();
    }
}

//출력 결과
5
6