[교재 EffectiveJava] 아이템 16. public 클래스에서는 public 필드가...

[교재 EffectiveJava] 아이템 16. public 클래스에서는 public 필드가...

728x90

public 클래스의 public 필드의 사용(하지마라)

public class Point { public double x; public double y; }

위 예제의 public 필드는 아주 위험하다. 이런 클래스는 데이터 필드에 직접 접근이 가능하게되면서, API를 수정하지 않고는 내부 표현을 바꿀 수 없고, 불변식을 보장할 수 없고, 외부에서 필드에 접근할때 부수 작업을 수행할 수도 없다. 이를 아래처럼 private 필드로 변경해야한다.

public 필드 사용시 문제가 없는 경우

package-private 클래스 혹은 private 중첩 클래스라면 데이터 필드를 노출한다해도 문제가 없다. 클라이언트 코드가 이 클래스를 사용한다 해도, 이 클래스를 포함하는 패키지 안에서만 동작하는 코드이므로, 패키지 바깥 코드에서는 데이터 표현 방식을 변경할 수 있다. private 중첩 클래스의 경우라면 수정 범위가 더 좁아져서 이 클래스를 포함하는 외부 클래스까지로 제한된다.

public 클래스의 private 필드의 사용(하라)

public class PointPrivate { private double x; private double y; public PointPrivate(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } }

필드를 모두 private 로 변경하고, public 접근자 (getter/setter) 을 추가하였다. public 클래스에서라면 이 방식을 사용해야한다. 패키지 바깥에서 접근할 수 있는 클래스라면 접근자를 제공함으로써 클래스 내부 표현 방식을 언제든 바꿀 수 있는 유연성을 얻을 수 있다.

예외적으로 java.awt.package 패키지의 Point 와 Dimension 클래스(성능 이슈 존재)는 public 클래스임에도 public 필드를 사용중이다. 이 클래스들과 상관없이 우리는 public 클래스의 필드를 직접 노출하지 말라는 규칙을 지켜야한다.

public class PointFinal { private static final int HOURS_PER_DAY = 24; private static final int MINUTES_PER_HOUR = 60; public final int hour; public final int minus; /** 유효한 시간임을 보장 */ public PointFinal(int hour, int minus) { if (hour < 0 || hour >= HOURS_PER_DAY) { throw new IllegalArgumentException("시간 : " + hour); } if (minus < 0 || minus >= MINUTES_PER_HOUR) { throw new IllegalArgumentException("분 : " + minus); } this.hour = hour; this.minus = minus; } }

public 클래스가 필드를 공개하면 이를 사용하는 클라이언트가 생겨날 것이므로 내부 표현 방식을 마음대로 바꿀 수 없게된다. public 필드가 불변이라도 직접 노출할때의 단점은 불변성 외에는 모두 여전히 존재한다.

public final 로 선언된 필드는 인스턴스 생성 시점에서만 값이 셋팅된다. 생성자에 if 제어문을 추가하여 유효한 시간임을 보장할 수 있다.

from http://devfunny.tistory.com/542 by ccl(A) rewrite - 2021-10-15 12:01:38