[Java] 중첩 클래스란?

Yujeong·2024년 6월 30일
0

Java

목록 보기
20/22
post-thumbnail

중첩 클래스란?

중첩 클래스(Nested Class)는 클래스 안에 클래스를 중첩해서 정의한 클래스이다.

class Outer {
	...
	class Nested {
    	...
    }
}

중첩 클래스 분류

중첩 클래스는 클래스를 정의하는 위치에 따라 분류할 수 있다.

  • 정적 중첩 클래스(Static Nested Class)
  • 내부 클래스
    • 내부 클래스(Inner Class)
    • 지역 클래스(Local Class)
    • 익명 클래스(Anonymous Class)

중첩 클래스의 선언 위치에 따라 클래스가 달라지는 것이다.

  • 정적 중첩 클래스 → 정적 변수와 같은 위치
  • 내부 클래스 → 인스턴스 변수와 같은 위치
  • 지역 클래스 → 지역 변수와 같은 위치

중첩과 내부 차이

  • 중첩: 어떤 다른 것이 내부에 위치하거나 포함되는 구조적인 관계
  • 내부: 나의 내부에 있는 나를 구성하는 요소
  • 정적 중첩 클래스
    • static 붙음
    • 바깥 클래스와 전혀 다른 클래스
    • 바깥 클래스의 인스턴스에 소속되지 않음
  • 내부 클래스
    • static 붙지 않음
    • 바깥 클래스를 구성하는 요소
    • 바깥 클래스의 인스턴스에 소속됨

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

내부 클래스를 포함한 모든 중첩 클래스는 특정 클래스가 다른 하나의 클래스 안에서만 사용되거나, 아주 긴밀히 연결되어 있는 특별한 경우에만 사용한다.

1. 논리적 그룹화

  • 특정 클래스가 다른 하나의 클래스 안에서만 사용되는 경우
  • 해당 패키지 외에 다른 곳에서 사용될 필요가 없는 중첩 클래스가 외부에 노출되지 않음

2. 캡슐화

  • 바깥 클래스의 private 멤버에 접근할 수 있음
  • 긴밀하게 연결
  • 불필요한 public 메서드를 제거할 수 있음

정적 중첩 클래스

public class Outer {

	private static int outClassValue = 1;
    private int outInstanceValue = 2;
    
    static class Inner {
    	private int nestedInstanceValue = 3;
        
        public void print() {
        	// 자신의 멤버에 접근
        	System.out.println(nestedInstanceValue);
            
            // 바깥 클래스의 인스턴스 멤버에 접근 불가
            // System.out.println(outInstanceValue);
            
            // 바깥 클래스의 클래스 멤버에 접근
            System.out.println(Outer.outClassValue);
        }
    }
}
public class StaticNestedMain {
	
    public static void main(String[] args) {
    	Outer.Inner inner = new Outer.Inner();
        inner.print();
    }
}
3
1

정적 필드에 접근 하는 것은 중첩 클래스가 아니어도 클래스명.정적필드명으로 접근할 수 있다. 그러니까 그냥 클래스 2개를 따로 만든 것과 같다.
클래스 2개 만든 것과 정적 중첩 클래스와 차이는 private 접근 제어자에 접근할 수 있다는 것이다.

내부 클래스

내부 클래스는 static이 붙지 않는 인스턴스 멤버가 된다.

public class Outer {

	private static int outClassValue = 1;
    private int outInstanceValue = 2;
    
    class Inner {
    	private int innerInstanceValue = 3;
        
        public void print() {
        	// 자신의 멤버에 접근
        	System.out.println(innerInstanceValue);
            
            // 외부 클래스의 인스턴스 멤버에 접근 가능, private 접근 가능
            System.out.println(outInstanceValue);
    		
            // 외부 클래스의 클래스 멤버에 접근 가능, private 접근 가능
            System.out.println(outClassValue);
        }
    }
}
public class InnerMain {
	
    public static void main(String[] args) {
    	// 단독 생성 불가. 무조건 바깥 인스턴스가 있어야 함
    	Outer outer = new Outer();
    	Outer.Inner inner = outer.new Inner();
        inner.print();
    }
}
3
2
1

지역 클래스

  • 내부 클래스의 특별한 종류
  • 지역 변수와 같이 코드 블럭 안에서 정의
  • 인터페이스 구현 가능
  • 부모 클래스 상속 가능
public class Outer {
	private int outInstanceVar = 1;
    
    public void process(int paramVar) {
    	
        int localVar = 3;
        
        class Printer {
        	int value = 4;
            
            public void printData() {
            	// 자신의 인스턴스 변수에 접근 가능
            	System.out.println("value: " + value);
                
                // 자신이 속한 코드 블럭의 지역 변수에 접근 가능
                System.out.println("localVar: " + localVar);
                
                // 자신이 속한 코드 블럭의 매개변수에 접근 가능
                System.out.println("paramVar: " + paramVar);
                
                // 바깥 클래스의 인스턴스 멤버에 접근 가능
                System.out.println("outInstanceVar: " + outInstanceVar);
            }
        }
        
        Printer printer = new Printer();
        printer.printData();
    }
    
    public static void main(String[] args) {
    	Outer outer = new Outer();
        outer.process(2);
    }
}
value: 4
localVar: 3
paramVar: 2
outInstanceVar: 1

익명 클래스

  • 지역 클래스의 특별한 종류
  • 클래스의 이름이 없음 → 생성자를 가질 수 없음
  • 이름 없는 지역 클래스를 선언하면서 동시에 생성
  • 부모 클래스를 상속 받거나 인터페이스 구현해야 함
  • 클래스 별도로 정의하지 않고도 인터페이스나 추상 클래스를 즉석 구현할 수 있어 코드 간결해짐
  • 복잡하거나 재사용이 필요한 경우에는 별도의 클래스를 정의하는 게 좋음
public class Outer {

    private int outInstanceVar = 1;
    
    public void process(int paramVar) {
    
        int localVar = 3;
        
        Printer printer = new LocalPrinter() {
        
			int value = 4;

            @Override
            public void print() {
                System.out.println("value:" + value);
                System.out.println("localVar:" + localVar);
                System.out.println("paramVar:" + paramVar);
                System.out.println("outInstanceVar:" + outInstanceVar);
            }
        }
        
        printer.print();
    }
    public static void main(String[] args) {
        Outer main = new Outer();
        main.process(2);
	}
}
value: 4
localVar: 3
paramVar: 2
outInstanceVar: 1

참고
김영한의 실전 자바 - 중급 1편

profile
공부 기록

0개의 댓글

관련 채용 정보