내부 클래스란 하나의 클래스 내부에 선언된 또 다른 클래스를 말한다. 이러한 내부 클래스는 외부 클래스에 대해 긴밀한 관계일 때 선언할 수 있다.
// 내부 클래스를 사용하지 않았을 때
class A {
int i = 100;
B b = new B();
}
class B {
// A의 iv인 i에 접근하는 방법
void method() {
A a = new A(); // A 인스턴스 생성
System.out.println(a.i); //
}
}
class C {
B b = new B();
}
// 내부 클래스를 사용할 때
class A { // 외부 클래스
int i = 100;
B b = new B();
class B { // 내부 클래스
void method() {
System.out.println(i);
}
}
}
class C {
// B b = new B(); // 직접 접근 불가
}
내부 클래스의 종류와 유효범위(scope)는 변수와 동일하다. 따라서 변수가 선언위치에 따라 종류가 다르듯이 내부 클래스 또한 선언위치에 따라 다른 종류가 된다.
내부 클래스 | 특징 |
---|---|
인스턴스 클래스 | 외부 클래스의 멤버변수 선언위치에서 선언 외부 클래스의 인스턴스 멤버처럼 사용 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언된다 |
스태틱 클래스 | 외부 클래스의 멤버변수 선언위치에서 선언 외부 클래스의 static 멤버처럼 사용 외부 클래스의 static 멤버, static 메서드에서 사용될 목적으로 선언된다 |
지역 클래스 | 외부 클래스의 메서드나 초기화 블럭 안에서 선언 선언된 영역 내부에서만 사용 가능 |
익명 클래스 | 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용) |
class InnerClass{
// 인스턴스 영역
int iv = 0;
class InstanceInner{}
// static 영역
static int cv = 0;
static class StaticInner{}
// 로컬 영역
void method() {
int lv = 0;
class LocalInner{}
}
}
내부 클래스의 제어자는 멤버 필드에 사용 가능한 제어자와 동일하다.
class OuterClass {
class InstanceInner {
int iv = 100;
// static int cv = 100; // 에러! static 변수 선언 불가
final static int CONST = 100; // 상수라서 선언 가능
}
static class StaticInner {
int iv = 200;
static int cv = 200; // static 클래스만 static 멤버 선언 가능
}
void method() {
class LocalInner {
int iv = 300;
// static int cv = 300; // 에러! static 변수 선언 불가
final static int CONST = 300; // 상수라서 선언 가능
}
}
}
class InnerEx3 {
private int outerIv = 0;
static int outerCv = 0;
class InstanceInner {
int iiv = outerIv; // 외부 클래스의 private 멤버도 접근 가능
int iiv2 = outerCv;
}
static class StaticInner {
// 스태틱 클래스는 외부 클래스의 인스턴스 멤버에 접근할 수 없다
// int siv = outerIv;
static int scv = outerCv;
}
void myMethod() { // 지역 내부 클래스를 감싸고 있는 메서드의 상수만 사용 가능
int lv = 0; // 값이 바뀌지 않는 변수는 상수로 간주
final int LV = 0; // JDK1.8부터 final 생략 가능
class LocalInner {
int liv = outerIv;
int liv2 = outerCv;
// 외부 클래스의 지역변수는 final이 붙은 변수(상수)만 접근 가능
int liv3 = lv; // 에러!!!(JDK1.8부터 에러 아님)
int liv4 = LV; // OK
}
}
다른 클래스와 다르게 익명 클래스는 이름이 없다. 클래스의 선언과 동시에 객체를 생성하므로, 단 하나의 객체만을 생성하는 일회용 클래스이다. 생성자도 가질 수 없고, 단 하나의 클래스나 인터페이스만을 상속하거나 구현할 수 있다. 매우 제한적인 용도로 구현되는 메서드가 적은 클래스를 구현할 때 사용된다.
import java.awt.*;
class prac {
public static void main(String[] args) {
Button b = new Button("Start");
b.addActionListener(new ActionListener() { // 익명 클래스의 선언, 객체 생성
public void actionPerformed(ActionEvent e) { // 익명 클래스의 내용
System.out.println("ActionEvent occurred!!!");
}
}); // 익명 클래스의 끝
}
}