[Effective Java] 아이템16 - public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라

아래와 같은 클래스는 public이어서는 안된다.

class Point {
  public double x;
  public double y;
}
  • 데이터 필드에 직접 접근할 수 있어서 캡슐화 X
  • 클래스 자체를 수정하지 않는 한 클라이언트에서 이 클래스 내부 표현을 바꿀 수 없음
  • 클라이언트 측에서 값을 변경할 수 있으므로 불변식 보장이 안됨

1. public 클래스는 필드를 모두 private으로 바꾸고 접근자(getter)를 추가한다.

class Point {
  private double x;
  private double y;

  public double getX() {return x;}
  public double getY() {return y;}

  public void setX(double x) {this.x = x;}
  public void setY(double y) {this.y = y;}
}

실무에서 많이 본 코드일 것이다. (물론 캡슐화를 위한 코드였는지는 몰랐음 ㅋㅋ)

접근자를 제공한다면, 필드를 클라이언트가 사용하고 있어도 내구 구현방식을 자유롭게 변경할 수 있다.

실제로 java.awt.package.Point 클래스는 public 임에도 불구하고 필드를 public으로 노출하고 있다. 심각한 성능 문제는 오늘날까지도 해결되지 못했다. [아이템67]

public class Point extends Point2D implements java.io.Serializable {
    /**
     * The X coordinate of this {@code Point}.
     * If no X coordinate is set it will default to 0.
     *
     * @serial
     * @see #getLocation()
     * @see #move(int, int)
     * @since 1.0
     */
    public int x;

    /**
     * The Y coordinate of this {@code Point}.
     * If no Y coordinate is set it will default to 0.
     *
     * @serial
     * @see #getLocation()
     * @see #move(int, int)
     * @since 1.0
     */
    public int y;

    ... 중략
}

2. public 클래스의 필드가 불변이라면 공개해도 좋다.

불변이라면 불변식은 보장할 수 있다. 하지만 클라이언트 측에서 해당 값을 가공할 수는 없다.

public class Time {

	private static final int HOURS_PER_DAY 		= 24;
	private static final int MINUTES_PER_HOUR 	= 60;

	public final int hour;
	public final int minute;

	public Time(int hour, int minute) {
		this.hour = hour;
		this.minute = minute;
	}

}

댓글남기기