본문 바로가기
JAVA

[JAVA] 중첩 클래스의 종류, 특징

by 정공자씨 2024. 4. 23.

 

 

 

중첩 클래스(Nested Class)

개념

  • 하나의 클래스 내에 선언된 또 다른 클래스
  • 즉, 한 클래스 내에서 다른 클래스를 정의하여 사용
  • 외부 클래스의 멤버로써 중첩 클래스를 사용함

 

중첩 클래스를 사용하는 이유

  • 하나의 클래스가 여러 클래스와 관계를 맺는 경우에는 독립적으로 선언하여 사용하는 것이 좋지만
  • 특정 1개의 클래스와 관계를 맺는 경우에는, 관계를 맺은 클래스 내부에 선언하는 것이 좋음
    • 외부 클래스와는 서로 밀접한 관계가 있는 경우에
    • 2개의 클래스를 묶어서 한번에 관리하여 캡슐화를 증가 시키고, 유지보수에 도움을 줌

 

장점

  • 중첩 클래스를 사용하면, 두 클래스의 멤버들끼리 서로 쉽게 접근할 수 있음
  • 불필요한 관계 클래스를 내부에 감춰서, 코드의 복잡성을 줄일 수 있음

 

 

중첩 클래스의 4가지 종류

class OuterClass {  

    // Inner Class(내부 클래스)
    class InnerClass { ... }  
    
    // Static Nested Class(정적 중첩 클래스)
    static class StaticInnerClass { ... }      
}

 

1. Inner Class

  • Non-Static Nested class
  • 인스턴스 클래스

2. Static Nested Class

  • static Nested class
  • 정적 클래스

3. local class

  • 지역 클래스(로컬 클래스)

4. anonymous class

  • 익명 클래스

[ 외부클래스 ]
- 중첩 클래스를 감싸는 바깥 클래스


외부클래스의 멤버

1. 필드(멤버변수)
2. 메서드
3. 내부 클래스
class OuterClass {
    int num = 1;   // 멤버변수 
    public void print() { ... }   // 메서드   
    class InnerClass { ... }     // 내부클래스        
}​

 

 

 

 

 

클래스 내부에 선언되는 위치에 따른 분류

1. 클래스의 멤버로 선언되는 클래스

  • Inner Class(인스턴스 클래스)
  • Static Nested Class(정적 클래스)

2. 메서드 내부에 선언되는 클래스

  • Local Class(로컬 클래스)
여러 단어를 혼용하여 쓰기 때문에,  
Inner클래스는 인스턴스 클래스로, Static Nested 클래스는 정적 클래스 기준을 두고 설명함

 

 

인스턴스 클래스

class OuterClass {
	  class InnerClass { ... } // OuterClass 객체를 생성해야만 사용할 수 있는 InnerClass
}

개념

  • static 키워드 없이, 클래스의 내부에 선언된 클래스
  • 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언
    • 외부 클래스 객체의 필드와 메서드에 직접 접근이 가능함

 

클래스의 멤버

  • 인스턴스 멤버만 선언할 수 있음
    • 인스턴스 필드
    • 인스턴스 메서드
  • static 멤버는 선언 불가

 

특징

1. 외부 클래스의 인스턴스를 먼저 생성한 후에, 인스턴스 클래스의 인스턴스 생성이 가능

 

2. 인스턴스 클래스에서 외부 클래스의 멤버에 접근이 가능함

  • 외부 클래스의 멤버는 필드, 메서드, 내부 클래스이고, 이 멤버들끼리는 동일한 레벨
  • 따라서 인스턴스 클래스에서 외부 클래스의 멤버에 접근할 수 있음

3. 인스턴스 필드와 메소드만 선언이 가능하고 정적 필드와 메소드는 선언할 수 없음

  • 인스턴스 클래스의 멤버로 인스턴스 필드와 메서드만 가질 수 있고
  • 정적(static) 필드와 메서드는 선언할 수 없음

4. 외부 클래스에서는 인스턴스 클래스의 필드와 메서드에 접근할 수 없음

외부 클래스를 기준으로 인스턴스 클래스의 필드와 메서드를 지역변수로 보기 때문에 외부 클래스에서 접근이 불가능함

 

 

[ 주의 사항 ] 
1. 인스턴스 클래스에서 외부 클래스의 정적 필드와 메서드(static) 사용 시, 외부 클래스의 인스턴스를 생성하지 않아도 바로 사용 가능
2. 인스턴스 클래스의 멤버로 정적 필드와 메서드(static)를 가질 수 없음

 

 

 

인스턴스 클래스의 인스턴스 생성 방법

  • 먼저 외부 클래스의 인스턴스를 생성한 후 → 인스턴스 클래스의 인스턴스를 생성
OuterClass outer = new OuterClass();
Outer.InnerClass inner = outer.new InnerClass();
  1. 외부 클래스의 인스턴스를 생성한 후에, 같은 타입의 참조변수에 대입
  2. 참조변수1.new를 이용하여 내부클래스의 인스턴스를 생성한 후에, 내부클래스 참조변수에 대입

 

예제

public class Outer {  // 외부 클래스 선언

    // 외부 클래스의 필드: static변수, 인스턴스 변수 모두 사용 가능
    static int a = 10; 
    int b = 20;
    private int c = 30;

    // 외부 클래스의 메서드: static메서드, 인스턴스 메서드 모두 사용 가능
    void outerInstanceMethod(){
        System.out.println("외부 클래스의 인스턴스 메서드");
    }

    static void outerStaticMethod(){
        System.out.println("외부 클래스의 정적 메서드");
    }

    // 내부 클래스(non-static inner class) 선언
    class Inner{
    	
        // 내부 클래스 안에서 static변수 사용 X
        // static int d = 40;
        
        int e = 50;
        private int f = 60;
        
        Inner(){}  // 기본 생성자
        
        Inner(int num1, int num2, int num3){  // 매개변수 있는 생성자
            a = num1;  // 외부 클래스의 필드를 제한 없이 사용 가능
            
            // 외부 클래스의 필드를 불러오기 위해서 this.를 사용 X
            Outer.this.c = num2;  // 외부클래스명.this.c 사용
            
            this.f = num3;  // 내부 클래스 자신의 필드를 불러오기 위해 this.를 사용
        }
        
        void instanceMethod(){
            System.out.println("내부 클래스의 인스턴스 메서드");
            System.out.printf("%d, %d, %d, %d, %d \n", a, b, c, e, f);
            
            // 외부 클래스의 필드를 제한 없이 사용 가능
            outerStaticMethod();
            outerInstanceMethod();
        }
        
       // 내부 클래스에서 static 메서드 사용 X
       // static void staticMethod(){
       //     System.out.println("내부 클래스에서 static 메서드 사용 불가");
       // }

    }
}

 

public class InnerTest {
    public static void main(String[] args) {
        // 1. 외부 클래스의 인스턴스를 생성
        Outer out = new Outer(); 

        // 2. 내부 클래스의 인스턴스를 생성
        Outer.Inner inner = out.new Inner(1, 2, 3);

        // 3. 내부 클래스의 인스턴스메서드 호출
        inner.instanceMethod();
    }
}

 

 

인스턴스 클래스의 컴파일 형태

  • 내부 클래스는 클래스 안의 클래스 형태이기 때문에, 보통의 컴파일과 형태가 다름
  • 컴파일시 생성되는 클래스 파일명은 외부클래스$내부클래스.class 형태
내부 클래스는 다른 클래스에서 직접 사용하는 것보다 해당 외부 클래스에서만 사용하는 것이 일반적이기 때문에
내부 클래스의 인스턴스 생성은, 주로 외부 클래스 내에서 이루어짐

 

 

 

 

 

 

정적 클래스

개념

  • static 키워드로 선언된 내부 클래스

 

클래스의 멤버

  • 인스턴스 필드와 메서드
  • 정적 필드와 메서드
  • 모두를 선언하여 사용할 수 있음

 

형식

class OuterClass {  // 외부 클래스
    static class InnerClass { ... }        
}

 

특징

  1. 정적 클래스의 객체를 생성하려면, 외부 클래스의 객체를 생성할 필요 없이 바로 생성 가능
  2. 내부 클래스에서 외부 클래스의 인스턴스 멤버에는 접근이 불가능함
public class CaptionTv {
    public int channel;  // 인스턴스 멤버변수
       
    static class Tape {  
        void showChannel() {       	
            // 외부 클래스의 인스턴스 멤버 접근 불가  
            // System.out.println(channel);   
        }        
    }
}​

 

   3. 외부 클래스의 멤버가 정적 멤버(static)라면, 내부클래스에서 외부 클래스의 멤버에 접근 가능

public class CaptionTv {
    static int channel;  // 정적 멤버변수
    int price;
       
    static class Tape {   
    	static String name = "테이프";
        int length = 10;
        
        void showChannel() {        
            // 외부 클래스의 인스턴스 멤버 접근 불가능
            // System.out.println(price);

            // 외부 클래스의 스태틱 멤버 접근 가능
            System.out.println(channel);        
        }        
        
        static void staticName() {  // 스태틱 메서드        
            // 스태틱 클래스의 멤버도, 스태틱 멤버만 접근 가능
            System.out.println(name);        
        }  
    }
}​

 

 

정적 클래스의 인스턴스를 생성하는 방법

  • 외부 클래스(Outer)의 인스턴스를 생성하지 않고,
  • 바로 정적 클래의 인스턴스를 생성해서 사용 가능
// 바로 내부 스태틱 클래스의 인스턴스를 생성
CaptionTv.Tape inner = new CaptionTv.Tape();

// 참조변수.정적메서드()
inner.staticName();

// 외부클래스.스태틱클래스.정적메서드()
CaptionTv.Tape.staticName();

 

 

예제

public class Outer {  // 외부 클래스 선언

    // 외부 클래스의 필드: static변수, 인스턴스 변수 모두 사용 가능
    static int a = 10; 
    int b = 20;
    private int c = 30;

    // 외부 클래스의 메서드: static메서드, 인스턴스 메서드 모두 사용 가능
    void outerInstanceMethod(){
        System.out.println("외부 클래스의 인스턴스 메서드");
    }

    static void outerStaticMethod(){
        System.out.println("외부 클래스의 정적 메서드");
    }

    // 정적 내부 클래스(static inner class) 선언
    static class StaticInner {
        static int d = 40;  
        int e = 50;
        private int f = 60;       
        
        void instanceMethod(){
            System.out.println("정적 내부 클래스의 인스턴스 메서드");
            
            // 외부 클래스의 인스턴스 필드는, 외부 클래스의 객체 생성 후 사용 가능
            Outer outer = new Outer();
            System.out.printf("외부 클래스의 인스턴스 필드 : %d, %d\n", outer.b, outer.c);
                  
            outer.outerInstanceMethod();
            
            // 외부 클래스의 정적 필드(static)는, 객체 생성 없이 사용 가능
            System.out.printf("외부 클래스의 정적 필드 : %d, %d \n", a, d);
            
            outerStaticMethod(); 
        }
        
        static void staticMethod(){
            System.out.println("정적 내부 클래스의 정적 메서드");
            
            // 외부 클래스의 정적 필드(static)는 객체 생성 없이 사용 가능
            System.out.printf("외부 클래스의 정적 필드 : %d, %d \n", a, d);

            outerStaticMethod();  
            
            // 외부 클래스의 인스턴스 필드는, 외부 클래스의 객체 생성 후 사용 가능
            Outer outer = new Outer();
            System.out.printf("외부 클래스의 인스턴스 필드 : %d, %d\n", outer.b, outer.c);
                  
            outer.outerInstanceMethod();
        }
    }
}

 

 

정적 클래스의 객체 생성하고, 정적 클래스의 인스턴스 메서드 호출
public class InnerClass {
    public static void main(String[] args) {

        Outer.StaticInner staticInner = new Outer.StaticInner();		
        staticInner.instanceMethod();	
    }
}

[ 실행 결과 ]

 

 

정적 클래스의 객체 생성하고, 정적 클래스의 정적 메서드 호출
public class InnerClass {
    public static void main(String[] args) {

        Outer.StaticInner staticInner = new Outer.StaticInner();		
        staticInner.staticMethod();	
    }
}

[ 실행 결과 ]

 

 

 

 

 

로컬 클래스

class OuterClass {
    void method() {
          class LocalClass { ... } // method()가 실행될 때만 사용할 수 있는 중첩클래스
    }
}

 

개념

  • 메서드 내에 선언한 중첩 클래스

 

클래스의 멤버

  • 인스턴스 필드와 메서드만 사용 가능
  • 정적 필드와 메서드는 선언 불가 

 

특징

  • 로컬 클래스에는 접근 제한자 및 static 키워드를 붙일 수 없음
  • 로컬 클래스 내부에는 인스턴스 필드와 메서드만 선언이 가능함
    • 정적 필드와 메서드는 선언할 수 없음
  • 메서드가 실행될 때, 메서드 내에서 로컬 클래스의 객체를 생성하고 사용해야 함
[ 주의할 점 ]
1. static 키워드 사용 불가
2. 정적 필드와 메서드 선언 불가

 

 

 

 

 

 

 

 

출처

 

java/ 내부 클래스의 종류와 내부 클래스를 사용함으로써 얻는 장점

내부 클래스 Inner Class = 이너 클래스, 중첩 클래스 내부 클래스는 클래스나 인터페이스 내에서 선언된 클래스를 말한다. 외부 클래스와 내부 클래스가 서로 연관되어 있을 때 사용할 수 있으며

romcanrom.tistory.com

 

☕ 내부 클래스(Inner Class) 장점 & 종류 총정리

내부 클래스 (Inner Class) 내부 클래스(inner class)란 하나의 클래스 내부에 선언된 또 다른 클래스를 의미한다. 보통 사용자 클래스 자료형이 필요하면, 메인 클래스 외부에 선언하거나, 따로 독립적

inpa.tistory.com

 

 

[Java] 중첩 클래스

1. 중첩 클래스란? 클래스 내부에 선언한 클래스 public class 클래스 { class 중첩클래스 { } } 중첩 클래스를 쓰는 이유 객체 지향 프로그램에서 클래스들은 서로 긴밀한 관계를 맺고 상호작용을 합니

veneas.tistory.com