Programming/JAVA

[Effective Java] public static final

코딩의성지 2023. 2. 7. 01:05

만약 클래스의 특정 필드를 public으로 열어두면 어떤일이 발생할까? public 으로 공개된 필드는 Thread Safe 하지 못하다. 즉 Lock 관련 작업(synchronized 로 처리한다거나 @Transactional 어노테이션으로 순서를 보장한다던가 하는 작업...)을 걸 수가 없다는 뜻이다. 이는 프로그램에 심각한 문제를 일으킬 수 있는 요소가 된다.

예를 들어 은행 계좌 클래스가 있거 금액을 의미하는 필드가 있을때 이 필드가 public으로 제공이 되는 경우에는 동시 다발적으로 금액 필드에 접근하여 심각한 문제를 야기할 수 있다는 말이다.

 

만약에 정말 필요한 상수로 사용할 생각이라면 필드를 public static final 을 통해서 공개가 가능하다.

private class Item {
    public static final float USD_EXCHANGE_RATE = 1261.95f;
    public static final float EUR_EXCHANGE_RATE = 1354.35f;

    private String name;
    private int price;
    public float getDolorPrice() {
    	return USD_EXCHANGE_RATE/price;
    }
    public  getEuroPrice() {
    	return EUR_EXCHANGE_RATE/price;
    }
    public int getWonPrice() {
    	return price;
    }
}

위의 코드처럼 달러와 유로의 환율 정보를 상수화 시켜놓으면, 나중에 환율이 변경되어도 해당 상수값만 수정해주면 해결이 된다. 너무 기초적인 이야기이다.

 

그런데 public static final 키워드를 쓸 데에도 배열에 대해서 사용에 주의가 필요하다. 배열 내부의 값은 단지 참조하는 값이기 때문에 수정이 될수 있기 때문이다. 배열을 상수화 시키기 위해서는 별도의 처리가 필요하다.

 

이는 두가지 방법으로 해결이 가능하다.

1. 배열을 private 로 만들고 불변리스트를 추가하기

private static final Member[] MEMBER_ARR = { ... };
public static final List<Member> MEMBER_LIST = Collections.unmodifiableList(Arrays.asList(MEMBER_ARR));

이 경우에는 특정 뷰 객체를 이용하여 읽기전용으로 respone해주는 방식이다. 허나 이 방법도 완벽한 방법은 아니다. 원본 의 값이 변경될 경우 읽기전용인 뷰도 결국 변경이 된다.

 

2.배열을 private로두고 복사본을 반호나하는 public method 만들기

private static final Member[] MEMBER_ARR = { ... };
public static final Member[] values() {
	return MEMBER_ARR.clone();
}

이렇게 되면 values 메서드를 호출하는 시점으로 값이 복사되고, 이 경우엔 원본의 값이 바뀌더라도 같이 변경되지 않게 된다.

 

 

반응형