중첩 클래스는 클래스 안에 정의한 클래스를 말한다.
이러한 중첩 클래스는 정의하는 위치에 따라 분류가 달라진다.
- non-static
- 내부 클래스 (inner)
- 지역 클래스 (local) : 코드 블록에 선언
- 익명 클래스 (anonymous) : 이름 없는 클래스
- static : 정적 중첩 클래스
non-static 같은 경우는 바깥 인스턴스 소속이고
static은 전혀 다른 인스턴스라고 한다.
음... 이게 무슨말인지 알아보도록 하자.
정적 중첩 클래스는 정적 변수와 같이 앞에 static
이 붙어있다.
public class Outer {
private static int outClassValue = 3;
private int outInstanceValue = 2;
static class Nested {
private int value = 1;
public void print() {
//자신의 멤버 접근
System.out.println(value);
//바깥 클래스의 인스턴스 멤버 접근 불가
//System.out.println(outInstanceValue);
//바깥 클래스의 클래스 멤버 접근 가능, private 접근 가능
System.out.println(outClassValue);
}
}
}
위의 예제 코드를 보면 Nested
클래스는 static
으로 생성된 것을 볼 수 있다.
그리고 이 클래스는 자신의 멤버는 당연 접근할 수 있고 Outer
클래스의 outClassValue
에도 접근할 수 있는 것을 볼 수 있다. static
으로 생성된 변수이기 때문에 당연히 접근할 수 있다!
하지만 여기서 중요한 것은 private
접근제어자에도 접근할 수 있다는 것이다.
//생성
Outer outer = new Outer();
Outer.Nested nested = new Outer.Nested();
생성은 위와같이 new Outer
에서 바로 .Nested()
를 할 수 있다! 이게 static
중첩 클래스의 특징이다. outer
인스턴스를 거치지 않고 직접 만들 수 있는데...
사실 이런 정적 중첩 클래스
는 다른 클래스를 중첩해서 만든 것일 뿐이라고 한다.
class Outer{}
class Nested{}
이런 식으로 그냥 따로 만든 것과 같은데, 유일한 차이는 앞에서 말했듯이 같은 클래스에 만들었기 때문에 private
접근 할 수 있다는 점이라고 한다.
으으음.. 뭐 대강 이해는 했다
Outer.Nested nested = new Outer.Nested(); -> 이렇게 생성 가능하고
Outer 클래스의 private static 변수에 접근가능하다!
내부 클래스는 앞서 알아본 정적 중첩 클래스와 달리 바깥 클래스의 인스턴스를 이루는 요소가 된다고 한다. 쉽게 얘기해서 내부 클래스는 바깥 클래스의 인스턴스에 소속 된다고...
이것도 바로 알아보자
public class Outer {
private static int outClassValue = 3;
private int outInstanceValue = 2;
class Inner {
private int value = 1;
public void print() {
//자신의 멤버에 접근
System.out.println(value);
//바깥 클래스의 인스턴스 멤버에 접근 가능. private 접근 가능
System.out.println(outInstanceValue);
//바깥 클래스의 클래스 멤버에 접근 가능. private 접근 가능
System.out.println(outClassValue);
}
}
}
내부 클래스는 모든 멤버 변수에 접근이 가능하다. 왜??
//생성
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
생성하는 것에서부터 차이가 좀 보인다. 여기서는 outer
인스턴스를 거쳐서 내부 클래스를 생성하고 있다.
이렇게 먼저 Outer
를 생성하고 Inner
를 생성하기 때문에 인스턴스 변수에도 접근이 가능한 것!
이게 바로 내부 클래스는 바깥 클래스의 인스턴스에 소속된다는 뜻이다. 바깥 클래스의 인스턴스 참조가 필요하다는 뜻. 그래서 outer.new Inner();
와 같은 방식으로 생성을 하는 것이고 Outer
의 모든 멤버 변수에 접근이 가능하다.
중첩 클래스는 특정 클래스Inner
가 다른 하나의 클래스 안Outer
에서만 사용되거나, 둘이 아주 긴밀하게 연결되어 있는 특별한 경우에만 사용해야 한다고 한다. 외부 여러곳에서 특정 클래스Inner
를 사용한다면 중첩 클래스가 아닌 그냥 일반적으로 클래스로 생성해서 사용하는게 좋다.
그렇다면 이렇게 중첩 클래스를 사용하는 이유는 뭘까?
- 논리적 그룹화 : 특정 클래스가 다른 하나의 클래스 안에서만 사용되는 경우 해당 클래스 안에 포함하는 것이 논리적으로 더 그룹화가 된다.
- 캡슐화 : 중첩 클래스는 바깥 클래스의
private
멤버에 접근할 수 있다. 이렇게 해서 둘을 긴밀하게 연결하고 불필요한public
메서드를 제거할 수 있다.
위와 같은 이유가 있다고 한다... 음.. 실제로 중첩 클래스를 많이 사용해보지 않아서 확 와닿지는 않는다. 예제를 더 많이 봐야겠다.
- 김영한의 실전 자바 - 중급 1편