아이템 16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라.
핵심 정리
클라이언트 코드가 필드를 직접 사용하면 캡슐화의 장점을 제공하지 못한다.
[아이템 15에서 나열되었던] 캡슐화의 장점
시스템 개발 속도를 높인다.
시스템 관리 비용을 낮춘다.
성능 최적화에 도움을 준다.
소프트웨어 재사용성을 높인다.
시스템 개발 난이도를 낮춘다.
필드를 변경하려면 API를 변경해야 한다.
x, y 의 이름이 변경되어야 한다면, 해당 필드를 사용하는 모든 코드들을 변경해야한다.
필드에 접근할 때 부수 작업을 할 수 없다.
x, y 에 제한을 추가하는 등의 (0 이상, 100 미만의 값이어야한다. 등) 부가적인 작업을 할 수 없다.
public class Point {
// 캡슐화의 장점을 제공하지 못한다.
public double x;
public double y;
public static void main(String[] args) {
Point point = new Point();
point.x = 10;
point.y = 20;
System.out.println(point.x);
System.out.println(point.y);
}
}
package-private 클래스 또는 private 중첩 클래스라면 데이터 필드를 노출해도 문제가 없다.
public 클래스는 한번 사용되면 어디서 어떻게 사용될지 예측이 불허하다.
그렇기 때문에 파급효과가 더 클 것이다.
package-private 클래스라면 데이터 필드를 노출해도 문제가 적어지기는 하다.
변경점이 적기 때문이다.
그럼에도 메서드를 통해 접근하도록 하는 할 때, 캡슐화의 장점을 모두 가져올 수 있다.
class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = 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; }
}
public final int hour 는 불변 필드이기 때문에 가변 필드보다는 안전하다.
여전히 부가적인 작업을 하지 못하며, 네이밍이 변경되어도 모든 코드에서 변경이 필요하다.
가변필드라면 사용하는 스코프에서 해당 값을 바로 사용하는 것이 아니라, 복사를 해서 사용해야한다.
해당 값을 바로 사용하면서 어디서 어떻게 값이 변할 여지가 있는지 모두 다 확인하기도 어렵고, 실수는 일어날 수 있기 때문이다.
public final 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) {
if (hour < 0 || hour >= HOURS_PER_DAY)
throw new IllegalArgumentException("Hour: " + hour);
if (minute < 0 || minute >= MINUTES_PER_HOUR)
throw new IllegalArgumentException("Min: " + minute);
this.hour = hour;
this.minute = minute;
}
// 나머지 코드 생략
}
완전 공략
p103, 아이템 67에서 설명하듯, 내부를 노출한 Dimension 클래스의 심각한 성능 문제는 오늘날까지도 해결되지 못했다.
내부를 확인하면 public 필드임을 알 수 있다.
즉, 객체를 사용할 때 값을 복사해서 사용해야 안전하기 때문에 불필요한 객체 생성이 필요하다.
한, 두 개라면 문제가 되지 않지만 수백만 개를 사용한다면 심각한 성능 문제 및 불편함(불필요한 객체 생성)이 야기된다.
public class DimensionExample {
public static void main(String[] args) {
Button button = new Button("hello button");
button.setBounds(0, 0, 20, 10);
Dimension size = button.getSize();
System.out.println(size.height);
System.out.println(size.width);
}
}
public class Dimension extends Dimension2D implements java.io.Serializable {
/**
* The width dimension; negative values can be used.
*
* @serial
* @see #getSize
* @see #setSize
* @since 1.0
*/
public int width;
/**
* The height dimension; negative values can be used.
*
* @serial
* @see #getSize
* @see #setSize
* @since 1.0
*/
public int height;
아이템 16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라.
핵심 정리
0 이상, 100 미만의 값이어야한다.
등) 부가적인 작업을 할 수 없다.public final int hour
는 불변 필드이기 때문에 가변 필드보다는 안전하다.복사
를 해서 사용해야한다.완전 공략
복사
해서 사용해야 안전하기 때문에 불필요한 객체 생성이 필요하다.