본문 바로가기
Java

Java 중급 1 - 중첩클래스, 내부 클래스(1)

by KongJiHoon 2025. 4. 12.

  • 클래스 안에 클래스를 정의하는 구조
  • 보통 특정 클래스 내부에서만 사용하는 클래스가 있을 때 사용
class Outer {
    class Inner {
        ...
    }
}

 

분류 클래스 이름 키워드 바깥 인스턴스와 관계
정적 중첩 클래스 Static Nested Class static 있음 ❌ 관계 없음
내부 클래스 Inner Class static 없음 ✅ 인스턴스에 소속
지역 클래스 Local Class 메서드 안
익명 클래스 Anonymous Class 이름 없음 ✅ (Local 확장)
  • 실무
    • 실무에서는 중첩, 내부라는 단어를 명확하게 구분 x
      중첩클래스 또는 내부 클래스라고 이야기한다. 클래스 안에 클래스가 있는것을 중첩 클래스라고 하고, 내부클래스도 중첩 클래스의 한 종류이므로 이 둘을 명확히 구분하지 않는다.
  • 사용 이유
    • 논리적 그룹화
      • 특정 클래스가 다른 하나의 클래스 안에서만 사용되는 경우 해당 클래스 안에 포함하는 것이 논리적으로 더 그룹화 된다. 패키지를 열었을 때 다른 곳에서 사용될 필요가 없는 중첩 클래스가 외부에 노출되지 않는 장점도 있다.
    • 캡슐화
      • 중첩 클래스는 바깥 클래스의 private 멤버에 접근할 수 있다. 이렇게 해서 둘을 긴밀하게 연결하고 불필요한 public 메서드를 제거할 수있다.

 

정적 중첩 클래스

package practice.nested;

public class NestedOuter {
    
    private static int outClassValue = 3;
    
    private int outInstanceValue = 2;

    
     static class Nested {
        
        private int nestedInstanceValue = 1;
        
        public void print() {

            System.out.println(nestedInstanceValue);

            // 바깥 클래스의 인스턴스 멤버에는 접근 할 수 없다.
            // System.out.println(outInstanceValue);

            // 바깥 클래스의 클래스 멤버에는 접근할 수 있다. private도 접근 가능
            System.out.println(outClassValue);
            
        }
        
    }
    
}
  • 정적 중첩 클래스
    • 자신의 멤버에는 당연히 접근 가능
    • 바깥 클래스의 인스턴스 변수에는 접근 x
    • 바깥 클래스의 static 변수에는 접근 가능
  • private 접근 제어자
    • private 접근 제어자는 같은 클래스 안에 있을 때만 접근 가능
    • 중첩 클래스도 바깥 클래스와 같은 클래스 안에 있다. 따라서 바깥 클래스의 private 접근 제어자에 접근 가능

 

package practice.nested;

public class NestedOuterMain {

    public static void main(String[] args) {

        NestedOuter outer = new NestedOuter();

        NestedOuter.Nested nested = new NestedOuter.Nested();

        nested.print();
        System.out.println("nestedClass = " + nested.getClass());


    }
}

 

실행결과

1
3
nestedClass = class practice.nested.NestedOuter$Nested

 

정적 중첩 클래스 활용

public class Network {
    public void sendMessage(String message) {
        NetworkMessage networkMessage = new NetworkMessage(message);
        networkMessage.print();
    }
}

 

public class NetworkMessage {
    private String content;
    public NetworkMessage(String content) { this.content = content; }
    public void print() { System.out.println(content); }
}

 

리펙토링

public class Network {
    public void sendMessage(String message) {
        NetworkMessage networkMessage = new NetworkMessage(message);
        networkMessage.print();
    }

    private static class NetworkMessage {
        private String content;
        public NetworkMessage(String content) {
            this.content = content;
        }
        public void print() {
            System.out.println(content);
        }
    }
}
  • NetworkMessage 클래스는 오직 Network 안에서만 사용되며, 외부에서는 사용되지 않는다. 이러한 경우 정적 중첩 클래스를 활용하면 외부에 노출되지 않으며, 내부적으로만 관리 가능한 구조로 만들 수 있다.
  • 또한 NetworkMessage는 Network 인스턴스에 의존하지 않기 때문에, 정적으로 선언하여 두 클래스 간의 불필요한 참조 의존성을 제거할 수 있다. 이는 객체지향 원칙 중 하나인 캡슐화(encapsulation)를 강화하는 동시에, 코드의 가독성과 유지보수성을 높여준다.

 

출처: 자바 중급 1 인프런 - 김영한