본문 바로가기
개발 공부/Java

이펙티브 자바 아이템 4 - 인스턴스화를 막으려거든 private 생성자를 사용하라 - 핵심 정리

by 개발인생 2022. 9. 20.
반응형
이 글은 백기선 님의 이펙티브 자바 강의와 이펙티브 자바 3 / E 편을 참고하여 작성하였습니다.

아이템 4 - 인스턴스화를 막으려거든 private 생성자를 사용하라 - 핵심 정리


인스턴스를 만들지 않는 걸 권장하는 경우가 있다.

특히 유틸리티성 클래스가 이에 해당한다.

static 메서드만 가지고 있는 클래스들을 유틸리티성이라고 한다.

대표적으로는 StringUtils 클래스가 있다.

public class UtilityClass {
   public static String hello() {
      return "hello";
   }
}

static 메서드만 가지고 있는 클래스가 있다.

   public static void main(String[] args) {
      String hello = UtilityClass.hello();
   }

위와 같이 static 메서드를 호출하여 사용한다.

인스턴스를 만들어 사용할수도 있지만 권장하는 방법은 아니다.

   public static void main(String[] args) {
      UtilityClass utilityClass = new UtilityClass();
      utilityClass.hello();
   }

문법적인 문제는 아니지만 권장하지 않는다.

오히려 해당 메서드가 인스턴스 메서드인지 스태틱 메서드인지 헷갈리게 만든다.

애초에 인스턴스를 만드는 걸 방지하도록 하자.

public abstract class UtilityClass {
   public static String hello() {
      return "hello";
   }
}

abstract 키워드를 붙여 추상클래스로 만들면 인스턴스 생성이 불가능해진다.

하지만 추상 클래스로 만들어도 인스턴스는 만들어질 수 있다.

public class DefaultUtilityClass extends UtilityClass{

}

추상 클래스를 상속받은 뒤

   public static void main(String[] args) {
      DefaultUtilityClass utilityClass = new DefaultUtilityClass();
      utilityClass.hello();
   }

위와 같이 인스턴스를 생성할 수 있게된다.

public class UtilityClass {
   private UtilityClass() {}

   public static String hello() {
      return "hello";
   }
}

private 생성자를 사용해 인스턴스 생성을 막을 수 있다.

private 생성자를 사용해도 내부에서 인스턴스를 만들 수 있다.

public class UtilityClass {
   private UtilityClass() {}

   public static String hello() {
      return "hello";
   }

   public static void main(String[] args) {
      UtilityClass utilityClass = new UtilityClass();
   }
}

이러한 경우를 방지하기 위해 에러를 발생시킬 수 있다.

public class UtilityClass {
   private UtilityClass() {
      throw new AssertionError();
   }

   public static String hello() {
      return "hello";
   }

   public static void main(String[] args) {
      UtilityClass utilityClass = new UtilityClass(); // 에러 발생
   }
}

AssertionError 를 발생시켜 인스턴스 생성을 못하게 막을 수 있다.

단점은 생성자가 보이는데 생성자를 만들면서까지 못쓰게 하는게 아이러니하다.

즉, 사용하지 못하는 코드를 만든 셈이다.

그렇기때문에

public class UtilityClass {
   /**
    * 이 클래스는 인스턴스를 만들 수 없습니다.
    */
   private UtilityClass() {
      throw new AssertionError();
   }

   public static String hello() {
      return "hello";
   }
}

주석을 사용해 문서화를 하도록한다.

이 방법은 Spring 에도 적용이 되어있지 않다.

Spring 에서는 주로 많은 유틸리티 클래스들이 abstract 를 사용해 인스턴스를 막고있다.

반응형

댓글