4. 인스턴스화를 막으려거든 private 생성자를 사용하라
유틸리티 클래스를 구현할 때 이건 꼭 지켜라!
📌 1. 발표 전 알아야 할 개념
✅ 유틸리티 클래스(Utility Class)
순수 정적 메서드만을 제공하는 클래스
자체적인 상태를 가지지 않고 순수한 기능만 제공한다
java.util.Arrays
,Math
,Collections
등
📕 2. 왜 정적 메서드만 있는 클래스를 만들까?
2-1. 기본 타입 값이나 배열을 다룰 때
Arrays
: 배열 조작을 돕는 유틸리티 클래스
import java.util.Arrays;
// 배열 관련 메서드
public class UtilArray {
public static void main(String[] args) {
int[] arr = {1, 5, 2};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
// 출력 : [1, 2, 5]
}
}
2-2. 특정 인터페이스를 구현하는 객체를 생성하는 메서드
Collections
: 불변 리스트를 만들어줌
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CollectionsExample {
public static void main(String[] args) {
// 고정된 크기의 리스트를 생성
List<String> list = Arrays.asList("A", "B", "C");
// Collections.unmodifiableList(list) → 읽기 전용 리스트로 변환
List<String> unmodifiableList = Collections.unmodifiableList(list);
// 리스트에 요소 추가 시도 → 불변 리스트이므로 예외 발생
// UnsupportedOperationException)
unmodifiableList.add("D");
}
}
2-3. final
클래스와 관련된 메서드
final
클래스와 관련된 메서드String
,Ingeter
,LocalDate
등final
클래스들은 상속이 불가하기 때문에 관련 추가 메서드는 유틸리티 클래스로 제공한다.
// String 관련 추가 메소드
// Objects 유틸리티 클래스
import java.util.Objects;
public class StringUtilityExample {
public static void main(String[] args) {
String str = null;
System.out.println(Objects.isNull(str));
// 출력 : true
}
}
🔑 3. 인스턴스화를 막아야 한다
유틸리티 클래스의 경우 모든 메서드가
static
이므로 객체 생성 없이 호출이 가능하다(유틸리티 클래스는 인스턴스로 만들어 쓰려고 설계한 클래스가 아니다!)불필요한 객체 생성은 메모리 낭비
[확장] 인스턴스화를 막을 수 있지 않나요?
생성자를 명시하지 않으면? (❌)
생성자를 명시하지 않으면, 자동으로 매개변수를 받지 않는
public
생성자 생성
추상 클래스로 만들면? (❌)
abstract
를 사용하는 추상 클래스는, new를 사용한 인스턴스 생성이 불가능하다단, 상속을 통해 하위 클래스를 만들면 인스턴스를 생성할 수 있다!
// 추상 메서드 abstract class Animal { abstract void sound(); } class Dog extends Animal { @Override void sound() { System.out.println("멍"); } } // Main 클래스 public class Main { public static void main(String[] args) { // Animal myDog = new Animal(); // 추상 클래스 생성 불가 // 상속 받은 하위 클래스 인스턴스 생성 가능능 Animal myDog = new Dog(); myDog.sound(); } }
💥 4. private
생성자를 추가하면 클래스의 인스턴스화를 막을 수 있다
private
생성자를 추가하면 클래스의 인스턴스화를 막을 수 있다명시적으로 생성자가
private
이므로 클래스 바깥에서 접근 불가어떠한 환경에서도 클래스가 인스턴스화하는 것을 막아준다
public class UtilClass {
private UtilClass() {
}
public static void utilMethod() {
System.out.println("인스턴스화 방지");
}
}
[추가 개념] enum
이 기본적으로 private
생성자를 가지는 것과 동일한 원리
--
💨 향후 확장 포인트
private
생성자를 사용하는 것은 상속을 금지하는 것과도 같다[Item19] 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라.
🤖 최종 결론
유틸리티 클래스는 인스턴스화할 필요가 없으므로
private
생성자를 사용해 인스턴스화를 막자자
❗어려웠던 점
final
클래스의 개념이 헷갈려 예시 작성에 어려움을 겪었다. String과 같은 쉬운 예제로 치환하니 이해가 쉬웠다.
😶🌫️ 느낀점
자바의 클래스 설계 방식은 다양하다
처음 아이템을 읽었을 때
enum
의 private 생성자와 비슷한 거 아닌가? 하는 생각이 들었는데 맞았다! 천천히 분석해서 읽고 내가 아는 기존의 개념과 연관짓는 습관을 들이자.
Last updated