자바 내부 클래스 및 정적 중첩 클래스
내부 클래스는 크게 두 가지 종류로 나눌 수 있습니다.
- 내부 멤버 클래스(Inner Member Class): 외부 클래스의 인스턴스 멤버와 마찬가지로 선언됩니다. 외부 클래스의 인스턴스를 통해서만 생성 및 접근할 수 있습니다. 외부 클래스의 멤버 변수와 메서드에 자유롭게 접근할 수 있으며, 외부 클래스의 private 멤버에도 접근할 수 있습니다.
- 정적 중첩 클래스(Static Nested Class):
static
키워드를 사용하여 선언됩니다. 외부 클래스의 인스턴스를 생성하지 않고도 직접 생성 및 접근할 수 있습니다. 외부 클래스의 정적 멤버만 접근할 수 있고, 외부 클래스의 인스턴스 멤버에는 접근할 수 없습니다.
내부 클래스의 장점:
- 코드의 가독성과 유지 관리성을 향상시킵니다. 관련 클래스를 하나의 코드 블록에 함께 묶어 놓을 수 있기 때문에 코드의 구조를 파악하기 쉬워집니다.
- 외부 코드로부터 은닉화하여 정보를 보호할 수 있습니다. 내부 클래스의 멤버는 외부 클래스에서 명시적으로 허용하지 않으면 접근할 수 없기 때문에 의도하지 않은 변경으로부터 데이터를 보호하는 데 도움이 됩니다.
- 재사용성을 높일 수 있습니다. 내부 클래스는 외부 클래스와 독립적으로 사용될 수 있기 때문에 다른 프로젝트에서도 쉽게 재사용할 수 있습니다.
정적 중첩 클래스의 장점:
- 외부 클래스의 인스턴스를 생성하지 않고도 사용할 수 있습니다. 이는 메모리 사용량을 줄이고 코드를 간결하게 만들 수 있다는 장점이 있습니다.
- 유틸리티 클래스와 같은 도구 클래스를 구현하는 데 유용합니다. 정적 중첩 클래스는 별도의 파일 없이 다른 클래스에서 쉽게 사용할 수 있는 정적 메서드와 변수를 제공할 수 있습니다.
사용 예시:
내부 멤버 클래스:
class OuterClass {
private int data = 10;
public class InnerClass {
public void accessOuterData() {
System.out.println("외부 클래스의 데이터: " + data);
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.accessOuterData();
}
}
class OuterClass {
public static class StaticNestedClass {
public static void printMessage() {
System.out.println("정적 중첩 클래스에서 메시지 출력");
}
}
public static void main(String[] args) {
OuterClass.StaticNestedClass.printMessage();
}
}
참고:
- 자바에서 내부 클래스 및 정적 중첩 클래스는 다양한 상황에서 유용하게 사용될 수 있는 강력한 기능입니다.
- 각 유형의 장점과 단점을 잘 이해하고 상황에 맞게 적절하게 사용하는 것이 중요합니다.
- 더 자세한 내용은 자바 공식 문서를 참고하시기 바랍니다.
// 내부 멤버 클래스 예제
class OuterClass {
private int data = 10;
public class InnerClass {
public void accessOuterData() {
System.out.println("외부 클래스의 데이터: " + data);
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.accessOuterData();
}
}
// 정적 중첩 클래스 예제
class OuterClass {
public static class StaticNestedClass {
public static void printMessage() {
System.out.println("정적 중첩 클래스에서 메시지 출력");
}
}
public static void main(String[] args) {
OuterClass.StaticNestedClass.printMessage();
}
}
OuterClass
라는 클래스가 있습니다.OuterClass
클래스에는data
라는 private 멤버 변수가 있습니다.OuterClass
클래스에는InnerClass
라는 내부 멤버 클래스가 있습니다.InnerClass
클래스에는accessOuterData()
라는 메서드가 있습니다.accessOuterData()
메서드는OuterClass
클래스의data
멤버 변수에 접근하고 출력합니다.main()
메서드에서OuterClass
클래스의 인스턴스를 생성하고,InnerClass
클래스의 인스턴스를 생성합니다.- 그리고
InnerClass
클래스의accessOuterData()
메서드를 호출하여OuterClass
클래스의data
멤버 변수 값을 출력합니다.
StaticNestedClass
클래스에는printMessage()
라는 정적 메서드가 있습니다.printMessage()
메서드는 "정적 중첩 클래스에서 메시지 출력"이라는 메시지를 출력합니다.main()
메서드에서OuterClass
클래스의StaticNestedClass
클래스의printMessage()
메서드를 직접 호출합니다.
- 위 예제 코드는 단순한 예시이며, 실제 상황에서는 더 복잡하게 사용될 수 있습니다.
- 간단한 작업을 수행해야 하는 경우 지역 변수를 사용하는 것이 가장 간단하고 효율적인 방법입니다.
- 지역 변수는 메서드 블록 내에서만 유효하며, 다른 메서드에서 직접 접근할 수 없습니다.
public class OuterClass {
public void someMethod() {
int data = 10; // 지역 변수
class InnerClass {
public void accessData() {
System.out.println("데이터: " + data);
}
}
InnerClass innerClass = new InnerClass();
innerClass.accessData();
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.someMethod();
}
}
익명 클래스 사용:
- 익명 클래스는 이름이 없는 내부 클래스입니다.
- 익명 클래스는 인터페이스를 구현하거나 추상 클래스를 상속할 때 사용됩니다.
- 익명 클래스는 간단한 인터페이스 또는 추상 클래스를 구현해야 하는 경우에 유용합니다.
public class OuterClass {
public interface InnerInterface {
void doSomething();
}
public void someMethod() {
InnerInterface innerInterface = new InnerInterface() {
@Override
public void doSomething() {
System.out.println("익명 클래스에서 작업 수행");
}
};
innerInterface.doSomething();
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.someMethod();
}
}
- 복잡한 작업을 수행해야 하는 경우 또는 내부 클래스를 다른 클래스에서 재사용해야 하는 경우 별도의 클래스를 사용하는 것이 좋습니다.
- 별도의 클래스는 더 나은 코드 구조와 유지 관리성을 제공합니다.
class InnerClass {
public void doSomething() {
System.out.println("별도의 클래스에서 작업 수행");
}
}
public class OuterClass {
public void someMethod() {
InnerClass innerClass = new InnerClass();
innerClass.doSomething();
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.someMethod();
}
}
Lambda 표현식 사용:
- Java 8 이상에서는 Lambda 표현식을 사용하여 익명 클래스를 더 간결하게 작성할 수 있습니다.
- Lambda 표현식은 간단한 작업을 수행하는 익명 클래스를 작성해야 하는 경우에 유용합니다.
public class OuterClass {
public interface InnerInterface {
void doSomething();
}
public void someMethod() {
InnerInterface innerInterface = () -> System.out.println("Lambda 표현식에서 작업 수행");
innerInterface.doSomething();
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.someMethod();
}
}
주의 사항:
- 내부 클래스를 대체하는 방법을 선택할 때는 각 방법의 장단점을 고려해야 합니다.
- 복잡한 상황에서는 여러 가지 방법을 조합하여 사용할 수도 있습니다.
java inner-classes static-classes