1. 내부 클래스란?
클래스 내부에 선언된 또 다른 클래스로, 외부 클래스의 멤버(필드/메서드)에 자유롭게 접근할 수 있으며, 밀접하게 관련된 기능을 함께 묶어 설계할 수 있도록 도와준다. 또한, 내부 클래스를 활용하면, 코드의 응집도를 높이고, 캡슐화를 강화할 수 있다.
1-2. 내부 클래스의 종류
| 구분 | 선언 위치 | 외부 클래스 접근 가능 여부 | 특징 |
| 1. 인스턴스 내부 클래스 | 외부 클래스의 멤버 위치 | 외부 인스턴스 변수 접근 가능 | 외부 클래스와 강한 결합 |
| 2. 정적(static) 내부 클래스 | 외부 클래스의 멤버 위치 | 외부의 static 멤버만 접근 가능 | static 키워드 사용, 독립성 높음 |
| 3.지역 내부 클래스 | 외부 클래스의 메서드 또는 초기화 블록 내부 | final 또는 effectively final 지역 변수 접근 가능 | 메서드 내에서만 사용 |
| 4. 익명 내부 클래스 | 클래스 정의와 인스턴스 생성을 동시에 | 외부 클래스 멤버 접근 가능 | 이름 없는 일회성 클래스 |
1-3. 사용하는 이유
1-3-1. 외부 클래스와 밀접한 기능을 묶기 위해
두 클래스가 강하게 연관된 관계라면 외부 클래스 내부에 클래스를 선언하는 것이 자연스럽다.
//예) 버튼 클릭 이벤트 리스너 등은 버튼 클래스 외부에서는 사용되지 않아 내부에 정의하는 것이 이상적
class Button {
class ClickListener {
void onClick() {
System.out.println("버튼이 클릭됨");
}
}
ClickListener event = new ClickListener();
// 버튼 클릭시
if(버튼클릭시) {
event.onClick();
}
}
1-3-2. 캡슐화(정보 은닉) 강화
내부 클래스를 private, protected로 선언하면 외부에서 접근이 불가 → 캡슐화 목적에 부합
class Outer {
private class HiddenHelper {//내부 구현을 숨기고 외부로 노출 X
void help() {
System.out.println("숨겨진 내부 로직 수행");
}
}
}
1-3-3. 응집도 증가 및 유지보수 향상
- 관련된 클래스를 물리적으로 하나의 파일 내부에 위치시켜 가독성과 관리성 향상
- DTO, 이벤트 처리 등에서 자주 사용됨
2. 멤버 내부 클래스
클래스의 멤버처럼 외부 클래스의 내부에 선언된 클래스를 말하며, 인스턴스 내부 클래스(non-static)와 정적 내부 클래스(static)로 구분된다.
2-1. 인스턴스 내부 클래스(Instance Inner Class)
외부 클래스 객체 생성 후 사용이 가능하며, 정적 멤버를 선언할 수 없다. 또한 외부 클래스의 인스턴스 멤버와 static 멤버 모두 접근이 가능하다.
class Outer {
private int num = 1; // 외부 클래스의 인스턴스 변수
private static int sNum = 2; // 외부 클래스의 static 변수
private InClass inClass; // 내부 클래스 자료형 변수 선언
public Outer() {
inClass = new InClass(); // 외부 클래스 생성자에서 내부 클래스 초기화
}
class InClass {
int inNum = 10; // 내부 클래스의 인스턴스 변수
void test() {
System.out.println("Outer num = " + num + "(외부 클래스의 인스턴스 변수)");
System.out.println("Outer sNum = " + sNum + "(외부 클래스의 정적 변수)");
}
}
public void testClass() {
inClass.test();
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println("외부 클래스를 통해 내부 클래스 메서드 호출");
outer.testClass();
}
}
2-2. 정적 내부 클래스(Static Inner Class)
외부 클래스의 인스턴스 없이도 생성이 가능하며, 외부 클래스의 static 멤버만 접근이 가능하다. 또한 정적 컨텍스트에서 주로 활용된다.
(※ static 멤버만 접근이 가능하다는게 중요!!!)
class Outer {
private int num = 3; // 외부 클래스의 인스턴스 변수
private static int sNum = 4; // 외부 클래스의 static 변수
void getPrint() {
System.out.println("인스턴스 메서드");
}
static void getPrintStatic() {
System.out.println("스태틱 메서드");
}
static class StaticInClass {
void test() {
System.out.println("Outer sNum = " + sNum + "(외부 클래스의 정적 변수)");
getPrintStatic(); // static 메서드 호출 가능
// System.out.println(num); → 에러 (인스턴스 멤버 접근 불가)
// getPrint(); → 에러 (인스턴스 메서드 접근 불가)
}
}
}
public class Main {
public static void main(String[] args) {
Outer.StaticInClass a = new Outer.StaticInClass(); // 외부 클래스 인스턴스 없이 사용
a.test();
}
}
3. 지역 내부 클래스
3-1. 정의 및 특징
3-1-1. 정의
외부 클래스의 메서드 내에 선언된 클래스로, 클래스의 멤버가 아닌 지역 변수처럼 메서드 안에서만 사용할 수 있다. 일반적으로 해당 메서드 안에서 정의 → 객체 생성 → 사용의 흐름으로 처리된다.
3-1-2. 특징
- 선언된 메서드 내부에서만 유효하다.
- 외부 클래스의 인스턴스 변수, 그리고 해당 메서드의 지역 변수에 접근할 수 있다.
- 단, 메서드의 지역 변수는 반드시 final이거나 effectively final(실질적으로 상수)이어야 한다.
- ※ effectively final이란?
- final이 없어도 변하지 않는 변수 → 테스트 코드를 만들 때 쓰인다.
- ※ effectively final이란?
// 지역 내부 클래스 예제
class Outer {
int num = 5; // 외부 클래스의 인스턴스 변수
void test() {
int num2 = 6; // 지역 변수
class LocalInClass {
void getPrint() {
System.out.println(num); // 외부 클래스 인스턴스 변수 접근
System.out.println(num2); // 지역 변수 접근 (final 또는 effectively final이어야 함)
}
}
LocalInClass localInClass = new LocalInClass(); // 지역 내부 클래스 객체 생성
localInClass.getPrint();
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.test(); // 지역 내부 클래스 실행
}
}
//effectively final 예제
void exampleMethod() {
int value = 100; // final은 생략했지만 값이 바뀌지 않음
class Inner {
void print() {
System.out.println(value); // 가능: effectively final
}
}
// value = 200; → 이 경우 에러! final 속성이 깨지므로 Inner에서 참조 불가
}'자바 고급(JAVA)' 카테고리의 다른 글
| JCF의 필요성과 구조 이해 (0) | 2026.05.20 |
|---|---|
| 익명 클래스(Anonymous Class) (0) | 2026.05.18 |
| SOLID 원칙 - DIP(Dependency Inversion Principle) (0) | 2026.05.15 |
| SOLID 원칙 - ISP(인터페이스 분리 원칙) (0) | 2026.05.15 |
| SOLID원칙 - LSP(리스코프 치환 원칙) (0) | 2026.05.15 |