반응형
이번 포스트에서는 Spring을 사용하다 보면 static 클래스나 메서드를 종종 보게되는데 왜 사용하는지 알아보자
1. Static이란 용어는 무엇을 의미할까?
- Java에서 static 키워드는 특정 클래스의 인스턴스가 아니라 클래스 자체에 속하는 필드나 메서드를 선언하는 데 사용된다. 이로 인해 static 필드나 메서드는 클래스의 모든 인스턴스에서 공유되며, 클래스 인스턴스 없이도 접근할 수 있다.
- Java에서 static 클래스는 주로 내부 클래스(inner class)에 사용되며, 이는 static 키워드가 사용된 내부 클래스가 외부 클래스의 인스턴스에 의존하지 않는다는 것을 의미한다.
- 즉, static 내부 클래스는 외부 클래스의 인스턴스 변수에 접근할 수 없으며, 외부 클래스의 인스턴스 없이도 생성될 수 있다.
2. static키워드를 사용하는 것의 장점
1. 독립성
- static 내부 클래스는 외부 클래스의 인스턴스에 의존하지 않는다. 따라서, 외부 클래스의 인스턴스 없이도 static 내부 클래스의 인스턴스를 생성하거나, static 내부 클래스의 메서드를 호출할 수 있다.
2. 캡슐화
- static 내부 클래스는 외부 클래스 내부에 선언되므로, 외부 클래스와 관련이 있는 로직을 그룹화하는 데 유용하다. 이는 코드의 가독성과 유지 관리성을 향상시킨다.
3. 네임스페이스 관리
- static 내부 클래스는 외부 클래스의 네임스페이스 내에 존재하므로, 이름 충돌을 방지하는 데 도움이 된다.
3. static을 사용하는 단점
1. 외부 클래스 접근 제한
- static 내부 클래스는 외부 클래스의 인스턴스 변수나 인스턴스 메서드에 접근할 수 없다. 따라서, 외부 클래스의 상태에 의존하는 로직을 static 내부 클래스에서 구현하려면 추가적인 작업이 필요하다.
- static 내부 클래스가 외부 클래스의 인스턴스 변수나 메서드에 접근하려면, 외부 클래스의 인스턴스를 명시적으로 참조해야 한다. 이를 위해 외부 클래스의 인스턴스를 static 내부 클래스의 생성자에 전달하거나, static 내부 클래스의 메서드에 매개변수로 전달할 수 있다.
public class OuterClass {
private int instanceVar;
public static class InnerClass {
public void printInstanceVar() {
// 아래 코드는 컴파일 에러를 발생시킵니다.
// System.out.println(instanceVar);
}
}
}
- 위의 코드에서 InnerClass의 printInstanceVar() 메서드는 외부 클래스의 instanceVar에 접근할 수 없다. 이를 해결하기 위해 외부 클래스의 인스턴스를 InnerClass의 생성자에서 전달할 수 있다.
public class OuterClass {
private int instanceVar;
public static class InnerClass {
private OuterClass outer;
// 이렇게 외부 클래스의 인스턴스를 InnerClass의 생성자에 전달한다.
public InnerClass(OuterClass outer) {
this.outer = outer;
}
public void printInstanceVar() {
// 이제 외부 클래스의 instanceVar에 접근할 수 있습니다.
System.out.println(outer.instanceVar);
}
}
}
- 이제 InnerClass의 인스턴스를 생성할 때 외부 클래스의 인스턴스를 전달하면, InnerClass에서 외부 클래스의 instanceVar에 접근할 수 있다.
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = new OuterClass.InnerClass(outer);
inner.printInstanceVar();
- 이렇게 외부 클래스의 인스턴스를 static 내부 클래스에 전달하는 방법은 static 내부 클래스가 외부 클래스의 상태에 의존해야 하는 경우에 유용하다. 그러나 이 방법은 static 내부 클래스의 독립성을 약간 손상시키므로, 필요한 경우에만 사용해야 한다.
2. 복잡성 증가
- static 내부 클래스를 과도하게 사용하면 코드의 복잡성이 증가할 수 있다. 특히, static 내부 클래스가 외부 클래스의 세부 구현에 의존하는 경우, 코드의 유지 관리성이 저하될 수 있다.
- 따라서, static 내부 클래스는 외부 클래스의 상태에 의존하지 않는 동시에 외부 클래스와 밀접하게 관련된 로직을 구현하는 데 적합하다. 예를 들어, static 내부 클래스는 특정 외부 클래스와 관련된 유틸리티 클래스, 빌더 클래스, 팩토리 클래스 등으로 사용될 수 있다.
4. static 키워드를 사용하는 주요 이유와 주의사항
1. 공유 상태 (Shared State)
- static 필드는 클래스의 모든 인스턴스 간에 공유된다.
- 예시: 게임에서 모든 플레이어가 공유하는 전체 점수를 관리할 때 static 필드를 사용할 수 있다.
2. 유틸리티 메서드 (Utility Methods)
- 객체의 상태에 의존하지 않고, 공통적인 기능을 제공하는 메서드에 사용된다.
- 예시: Math.abs(int a)는 절대값을 반환하는 static 메서드다.
3. 상수 (Constants)
- static final 필드는 변경 불가능한 상수를 선언하는 데 사용된다.
- 예시: Math.PI는 원주율 값을 상수로 선언한 static final 필드다.
4. 싱글턴 패턴 (Singleton Pattern)
- 클래스의 인스턴스를 하나만 생성하고 전역에서 접근할 수 있게 하는 패턴에 사용된다.
- 예시: 데이터베이스 연결을 관리하는 싱글턴 클래스에서 static 필드를 사용할 수 있다.
5. 내부 클래스 (Inner Classes)
- 외부 클래스의 인스턴스에 의존하지 않는 내부 클래스를 선언하는 데 사용된다.
- 예시: GUI 애플리케이션에서 이벤트 리스너를 static 내부 클래스로 선언할 수 있다.
6. 주의사항
- static 필드는 모든 인스턴스에서 공유되므로, 변경 시 모든 인스턴스에 영향을 미칠 수 있다.
- static 메서드는 객체의 상태에 접근할 수 없으므로, 매개변수와 static 필드만 사용할 수 있다.
- 상태를 공유해야 하는 경우나 상수를 선언하는 경우에만 static 필드를 사용하는 것이 좋다.
5. static 메서드의 사용과 제한 사항
1. static 메서드의 특징
- static 메서드는 클래스 레벨에서 작동하므로 특정 인스턴스의 상태에 접근할 수 없다.
- this 키워드를 사용할 수 없으며, 인스턴스 변수나 인스턴스 메서드를 직접 참조할 수 없다.
1-1. 예시 코드
public class Calculator {
public static int add(int a, int b) {
return a + b; // 인스턴스 변수나 this 키워드 없이 작동
}
}
2. static 메서드에서 사용할 수 있는 것들
- 메서드의 매개변수
- static 필드 (클래스 변수)
- static 메서드
- 메서드 내에서 선언된 지역 변수
3. static 메서드의 활용 예
- 유틸리티 메서드: 공통적인 기능을 제공하는 메서드로, Math 클래스의 Math.abs(int a)와 같은 메서드가 있다.
- 팩토리 메서드: 객체 생성을 캡슐화하는 메서드로, 인스턴스 생성 로직을 숨기고 객체를 생성하는 역할을 한다.
- 싱글턴 인스턴스의 접근자: 싱글턴 패턴에서 유일한 인스턴스에 접근하기 위한 메서드로 사용될 수 있다.
4. 결론
- static 메서드는 인스턴스의 상태에 의존하지 않는 작업을 수행하는 데 사용된다.
- 유틸리티 메서드나 팩토리 메서드와 같은 특정 케이스에서 유용하게 활용될 수 있다.
2023.08.09 - [Spring 기초/Spring + Java] - [스프링, 스프링부트] Spring, Java - 함수형 프로그래밍 (1)
2023.08.09 - [Spring 기초/Spring + Java] - [스프링, 스프링부트] Spring, JAVA - 익명 클래스 [개념 설명] (1)
반응형
'Spring + Java' 카테고리의 다른 글
[Spring] 자바 리플렉션과 생성자 주입의 관계 (1) | 2023.11.19 |
---|---|
[Spring] 스프링은 추상화를 어떻게 적용했을까? (0) | 2023.11.02 |
[Spring] 스프링의 익명 클래스 활용 (0) | 2023.08.09 |
[Spring] 스프링 빈(Bean)을 함수형으로 등록하기 (0) | 2023.08.09 |
[Spring] 함수형 프로그래밍이란? (0) | 2023.08.09 |