내부클래스는 클래스내에 선언된 클래스이다.
클래스안에 다른 클래스를 선언하는 이유는 두 클래스가 서로 긴밀한 관계에 있기 때문이다.
class A { // 외부 클래스
...
class B { // 내부 클래스
...
}
}
내부 클래스의 장점
- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
- 코드의 복잡성을 줄일 수 있다(캡슐화)
내부 클래스의 종류는 변수의 선언위치에 따른 종류와 같다.
내부클래스의 유효범위와 성질은 변수와 유사하다.
| 내부클래스 | 특징 |
|---|---|
| 인스턴스 클래스(instance class) | 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 인스턴스 멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언된다. |
| 스태틱 클래스(static class) | 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static멤버처럼 다루어진다. 주로 외부클래스의 static멤버, 특히 static메서드에서 사용될 목적으로 선언된다. |
| 지역 클래스(local class) | 외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다. |
| 익명 클래스(anonymous class) | 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용) |
내부 클래스의 선언위치에 따라 같은 선언위치의 변수와 동일한 유효범위(scope)와 접근성을 갖는다.
class Outer {
class InstanceInner {} // 인스턴스 클래스
static class StaticInner {} // 스태틱 클래스
void myMethod() {
class LocalInner {} //지역 클래스
}
}
내부 클래스도 클래스이기 때문에 abstract이나 final과 같은 제어자를 사용할 수 있을 뿐만 아니라, 멤버변수들처럼 private, protected과 접근제어자도 사용이 가능하다.
- 인스턴스 클래스
인스턴스 멤버이기 때문에 인스턴스 변수와 static변수를 모두 사용할 수 있다. 심지어 static변수의 접근 제어자가 private이어도 사용가능하다.- 스태틱 클래스
외부 클래스의 static멤버이기 때문에 외부 클래스의 인스턴스 멤버(인스턴스 변수와 인스턴스 클래스)를 사용할 수 없다. 단지 static멤버만을 사용할 수 있다.- 지역 클래스
외부 클래스의 인스턴스 멤버와 static멤버를 모두 사용할 수 있다. 지역클래스가 포함된 메서드에 정의된 지역변수도 사용가능한데 단, final이 붙은 지역변수만 접근이 가능하다.
(JDK1.8부터는 final이 자동으로 붙기 때문에 final을 따로 붙여주지 않아도 접근가능하다.)
컴파일 했을때 생성되는 파일명 :
'외부 클래스명$내부 클래스명.class'
class Outer {
void myMethod() {
class LocalInner {}
}
void myMethod2() {
class LocalInner {}
}
}
/*컴파일 결과
Outer.class
Outer$1LocalInner.class
Outer$2LocalInner.class */
익명 클래스는 특이하게도 다른 내부 클래스들과는 달리 이름이 없다. 클래스의 선언과 객체의 생성을 동시에 하기 때문에 단 한번만 사용될 수 있고 오직 하나의 객체만을 생성할 수 있는 일회용 클래스이다.
new 조상클래스이름() {
//멤버선언
}
또는
new 구현인터페이스이름() {
//멤버선언
}
익명 클래스의 사용 예
class InnerEx6 {
Object iv = new Object () {void method() {} }; //익명클래스
static Object cv = new Object () {void method() {} }; //익명클래스
void myMethod() {
Object lv = new Object () {void method() {} }; //익명클래스
}
}
/*컴파일 시 생성되는 파일
InnerEx6.class
InnerEx6$1.class <-익명클래스
InnerEx6$2.class <-익명클래스
InnerEx6$3.class <-익명클래스 */
**'외부클래스명$숫자.class'**의 형식으로 클래스파일명이 결정된다.