[Effective Java] Item 15. 상수로 사용하고자하는 필드값이 불변객체인지 고려해야한다

2024. 3. 16. 20:37Java/Effective Java

반응형

프로그램의 요소를 접근할 수 있는 권한은 최대한 최소화하는 것이 좋습니다.
반드시 공개되어야하는 요소들만 public으로 설정하는 것이, 유지보수 면에서도 좋습니다.

public 클래스 내의 가변 필드값들은 모두 private 으로 설정 하는 것을 권장하고
상수필드의 경우 필요에 따라 public으로 설정합니다

상수로 이용하고자하는 필드값에는 public static final 를 설정하는데,

이때 주의해야할 점이, reference 타입 중 몇몇 타입은 private static final을 설정하여도 내용을 수정할 수 있다는 점입니다.

변경가능한 레퍼런스 타입 필드값 (array, modifiable 컬렉션들) 의 경우 내용 private static final을 설정해도 변경이 가능하다.


예시 1

아래 예제코드에서 private static final을 설정하였으나, 값을 변경할 수 있는 것을 확인할 수 있습니다.

static final String[] arr = {"apple"};
public static void main(String[] args) {
    System.out.println(Arrays.toString(arr));
    arr[0] = "banana";
    System.out.println(Arrays.toString(arr));
}
[apple]
[banana]

예시 2

unmodifiable 리스트가 아닌 경우, private static final 설정을 하여도 내용을 수정할 수 있습니다.

private static final List<String> list = Lists.newArrayList("RED", "BLUE");
static void ex02() {
    System.out.println(list);
    list.set(0, "AAA");
    System.out.println(list);
}
[RED, BLUE]
[AAA, BLUE]

이러한 부분을 고려하지 않는다면, 변경되지 않아야하는 데이터가 어느시점에 변경되어 서비스에 영향을 줄 수 있습니다.

이런 부분을 방지하기 위해서는, 아래 2가지 방법을 사용할 수 있습니다.

  1. 불변 객체로 변환하여 사용하기
  2. 변경이 가능한 필드값은 private로 설정하고 해당 값을 복제한 값을 반환하는 메서드를 제공하기

1. 불변객체로 변환하여 사용하기

List.of를 이용하여 불변객체로 만든 후, 그 객체를 사용하면 외부에서 원치 않게 수정되는 일을 방지할 수 있고

변경하려 할때, .UnsupportedOperationException 익셉션이 발생합니다.

private static final String[] P_VALUES = {"apple", "melon", "peach"};
public static final List<String> VALUES = List.of(P_VALUES);

public static void main(String[] args) {
    System.out.println(VALUES);
    VALUES.set(0, "AAA"); // Exception 발생
}

2. 변경이 가능한 필드값은 private로 설정하고 해당 값을 복제한 값을 반환하는 메서드를 제공하기

아래와 같이, 변경이 가능한 필드값은 private으로 설정해두고,
해당값의 clone한 값을 리턴하는 public 메서드를 추가해줍니다.

fruits() 메서드의 리턴값인 fruits를 수정하더라도 원본에는 영향을 주지 않습니다.

private static final String[] P_VALUES = {"apple", "melon", "peach"};

public static final String[] fruits() {
    return P_VALUES.clone();
}
public static void main(String[] args) {
    String[] fruits = fruits();
    System.out.println(Arrays.toString(fruits));
    fruits[0] = "AAA";
    System.out.println(Arrays.toString(fruits));
    System.out.println(Arrays.toString(fruits()));
}
[apple, melon, peach]
[AAA, melon, peach]
[apple, melon, peach]

++

  • Item 15. 클래스와 멤버의 접근 권한을 최소화하라
728x90
반응형