❗️ 기존 Java 클래스의 아쉬운 점을 이해하고, 유틸클래스와 내부클래스📌 기존를 사용할 수 있다.
1️⃣ 클래스를 이용하려면 매번 인스턴스화 해야만 할까?
👉 Java static 적극 활용 (ex: 실행 클래스)
2️⃣ 여러 클래스/메소드 유사한 걸 표시하려면 상속해야만 할까?
👉 내부 클래스 문법 활용
3️⃣ 클래스 한 번만 이용할 건데, 새로 클래스 정의를 해야만 할까?
👉 내부 클래스 기법 활용
👉 static 적극 활용
static
으로 만들어두면 객체 생성 없이 호출 가능하다.// 유틸 클래스 예시
public class MathUtil {
public static int add(int a, int b) {
return a + b;
}
}
// 사용
System.out.println(MathUtil.add(3, 5)); // 8
✅ 장점: 객체 안 만들어도 됨.
✅ 실제 예시: Math.sqrt(), Collections.sort() 같은 표준 API.
public class Outer {
private String name = "정잉이";
// 내부 클래스
class Inner {
public void printName() {
System.out.println("이름은 " + name);
}
}
}
// 사용
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // outer인스턴스화 필요!
inner.printName(); // 이름은 정잉이
✅ 장점: 상속 없이 “연관된 클래스”를 한 곳에 묶어서 관리 가능.
✅ 예시: GUI 이벤트 처리 (Swing, Android 개발에서 자주 씀).
public class Outer {
private static String staticName = "정잉이";
private String instanceName = "인스턴스 정잉이";
// 정적 중첩 클래스
public static class Nested {
public void printName() {
// 외부 클래스의 static 멤버는 접근 가능
System.out.println("staticName: " + staticName);
// ❌ 외부 클래스의 인스턴스 변수는 접근 불가
// System.out.println(instanceName); // 컴파일 오류
}
}
}
public class Main {
public static void main(String[] args) {
// 외부 클래스 객체 필요 없음
Outer.Nested nested = new Outer.Nested();
nested.printName(); // staticName: 정잉이
}
}
1. 외부 클래스와 강한 연관은 있지만, 독립적으로도 동작해야 할 때
→ 예: Map.Entry<K, V>
(HashMap 안에 정의된 정적 중첩 클래스).
2. 도우미(Helper) 클래스 정의할 때 → 외부 클래스 안에만 쓰고 외부로 노출 안 하고 싶을 때.
✅ 외부 클래스 인스턴스와 연관이 있냐 없냐가 큰 핵심이다
구분 | 일반 중첩 클래스 (Inner Class) | 정적 중첩 클래스 (Static Nested Class) |
---|---|---|
선언 방식 | class Outer { class Inner {...} } | class Outer { static class Nested {...} } |
외부 클래스 인스턴스 필요 여부 | ✅ 필요 (Outer 객체 먼저 있어야 함) | ❌ 불필요 (Outer 없이도 독립 사용 가능) |
외부 인스턴스 멤버 접근 | ✅ 가능 (private 포함, 마치 자기 것처럼) | ❌ 불가능 (static 멤버만 접근 가능) |
메모리 구조 | 외부 클래스 인스턴스에 종속됨 | 외부 클래스와 독립적으로 존재 |
객체 생성 방법 | Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); | Outer.Nested nested = new Outer.Nested(); |
대표 사용처 | 이벤트 핸들러, GUI 처리 (외부 인스턴스와 강한 연관 필요) | Helper 클래스, Enum 내부 클래스, Map.Entry 같이 독립 동작 가능한 구조 |
public class Main {
public static void main(String[] args) {
String prefix = "안녕하세요!";
// main 메서드 안에 정의된 지역 내부 클래스
class Greeter {
public void greet(String name) {
// main 메서드의 변수(prefix)는 사실상 final이므로 접근 가능
System.out.println(prefix + " " + name);
}
}
// 지역 내부 클래스 객체 생성 후 사용
Greeter greeter = new Greeter();
greeter.greet("정잉이");
greeter.greet("철수");
}
}
안녕하세요! 정잉이
안녕하세요! 철수
Greeter
클래스는 main 메서드 안에서만 사용 가능main
)의 변수 prefix
를 접근할 수 있음 → 단, 사실상 finalinterface Greeter {
void greet();
}
public class Main {
public static void main(String[] args) {
// 익명 내부 클래스 사용
Greeter greeter = new Greeter() {
@Override
public void greet() {
System.out.println("안녕하세요, 익명 내부 클래스!");
}
};
greeter.greet(); // 안녕하세요, 익명 내부 클래스!
}
}
✅ 여러 번 인스턴스화 가능한지 한 번만 인스턴스화 가능한지가 핵심이다.
구분 | 지역 내부 클래스 | 익명 내부 클래스 |
---|---|---|
이름 | ✅ 있음 | ❌ 없음 |
재사용 | 가능 (메서드 안에서) | 한 번만 사용 |
정의 위치 | 메서드/블록 안 | 보통 인터페이스/추상 클래스 구현과 동시에 |
객체 생성 | 별도 | 클래스 정의 + 객체 생성 동시에 |