반응형
규칙 13에서 객체 필드 변수는 절대로 public으로 선언하지 말고 getter와 같은 접근자 메서드를 사용하라고 설명했다.
규칙 14에서는 위 내용에 대해 간단하게 설명한다.
객체 필드 변수를 public으로 선언하게 되면 외부에서 데이터를 쉽게 조작할 수 있어 캡슐화의 이점을 누릴 수 없다.
예를 들어 양수만 표현하는 Point 클래스를 아래와 같이 선언한다면 생성자에서는 음수를 넣을 수 없지만 정상적으로 객체 생성 후 클라이언트가 음수를 직접 세팅할 수 있다.
public class PositivePointWithPublicField {
public double x;
public double y;
public PositivePointWithPublicField(double x, double y) {
if (x < 0 || y < 0) {
throw new IllegalArgumentException();
}
this.x = x;
this.y = y;
}
}
public class Client {
public static void main(String[] args) {
PositivePointWithPublicField point = new PositivePointWithPublicField(0, 0);
point.x = -5;
point.y = -10;
}
}
하지만 필드를 private로 선언하고 getter를 사용하게 되면 위를 방지할 수 있다.
public class PositivePointWithPrivateField {
private double x;
private double y;
public PositivePointWithPrivateField(double x, double y) {
if (x < 0 || y < 0) {
throw new IllegalArgumentException();
}
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
public class Client {
public static void main(String[] args) {
PositivePointWithPrivateField point = new PositivePointWithPrivateField(0, 0);
// 컴파일 에러
point.x = -5;
point.y = -10;
}
}
getter 메서드(또한 setter)는 너무나 많이 사용하기 때문에 IDE에서 자동으로 생성해주는 기능이다. 뿐만 아니라 lombok과 같은 라이브러리에서는 어노테이션을 사용하여 자동으로 생성할 수 있다.
@Getter
public class PositivePointWithPrivateField {
private double x;
private double y;
public PositivePointWithPrivateField(double x, double y) {
if (x < 0 || y < 0) {
throw new IllegalArgumentException();
}
this.x = x;
this.y = y;
}
}
다만 Immutable 필드(final 선언)라면 초기에 한 번만 설정할 수 있으므로 public으로 선언하여도 아래와 같이 클라이언트가 조작하지 못하므로 public으로 선언해도 된다. 하지만 굳이 이럴 바에는 getter를 사용하는 게 더 맞다. 또한 public 필드를 두게 되면 후에 호환성을 위해 항상 해당 필드를 유지해야 한다. 하지만 getter를 제공한다면 이미 작성된 클라이언트 코드는 깨트리지 않을 수 있다.
public class PositivePoinWithFinalField {
public final double x;
public final double y;
public PositivePoinWithFinalField(double x, double y) {
if (x < 0 || y < 0) {
throw new IllegalArgumentException();
}
this.x = x;
this.y = y;
}
}
public class Client {
public static void main(String[] args) {
PositivePoinWithFinalField point = new PositivePoinWithFinalField(0, 0);
// final이서 컴파일 에러
point.x = -5;
point.y = -10;
}
}
참고
자바에서 제공하는 클래스 중에 규칙 14를 깨트린 클래스들이 존재한다. 따라서 이런 클래스는 코딩할 때 참고하지 않는 것이 좋다.
// java.awk.Point
public class Point extends Point2D implements java.io.Serializable {
public int x;
public int y;
// ...
}
// java.awk.Dimension
public class Dimension extends Dimension2D implements java.io.Serializable {
public int width;
public int height;
// ...
}
반응형
'Java > [책] 이펙티브 자바' 카테고리의 다른 글
[이펙티브자바] 규칙16. 계승보다 구성 (= extends보다 필드선언) (0) | 2022.03.20 |
---|---|
[이펙티브 자바] 규칙15. Immutable(불변) 클래스 (0) | 2022.03.09 |
[이펙티브 자바] 규칙13. 접근 제어(Access Control)는 최소화하자. (0) | 2022.02.14 |
[이펙티브 자바] 규칙12. Comparable, Comparator 인터페이스 (0) | 2022.01.07 |
[이펙티브 자바] 규칙11. Object.clone() 구현방법 (0) | 2021.12.28 |