가변객체의 위험성 -> 식별자 가변성
말그대로 식별자로서 사용되는 객체가 (가변객체이기 때문에) 변경되는 것이 허용되어있게 되는 것이고 , 이로 인해 예측하지 못한 일들이 벌어진다는 것이다.
Cash 타입의 객체들은 "값 객체" 처럼 생각하고 작성하였다.
private class Cash {
private int cash;
public Cash(int cash) {
this.cash = cash;
}
public void setCash(int cash) {
this.cash = cash;
}
public void mul(int operand) {
this.cash *= operand;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Cash cash1 = (Cash)o;
return cash == cash1.cash;
}
@Override
public int hashCode() {
return Objects.hash(cash);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Cash{");
sb.append("cash=").append(cash);
sb.append('}');
return sb.toString();
}
}
아래는 HashMap 의 키가 가변객체인 경우 일어나는 일에 대한 예시다.
Map 에 (five, "five") (ten, "ten") 을 집어넣고는, five 객체에 변경이 일어났다.
그렇다면 map 에서 five 라는 키를 사용하여 값을 찾아달라고 요청을 해 보자. 어떤 결과가 나올까?🥸
public static void main(String[] args) {
Map<Cash,String> map = new HashMap<>();
Cash five = new Cash(5);
Cash ten = new Cash(10);
map.put(five, "five");
map.put(ten, "ten");
System.out.println(map);
five.mul(2); // 값을 변경하였음
System.out.println(map);
System.out.println(map.get(five)); // ten 이 나온다
map.put(five, "five"); // map 에 대한 key 를 업데이트하자
System.out.println(map.get(five));
}
five 가 아닌 ten 이 나온다.
변경한 객체를 다시 map 에 넣으면, 이제 정상적으로 나온다. ( 기존의 map,value) 를 새로운 five 객체가 대체하게 되니까 당연한 일이다 )
이 때 map 출력해보면
HashMap 의 경우, 처음 element 를 집어넣을 때면, key 를 사용하여 해쉬값을 계산한다. 계산된 해쉬값을 기반으로 하여 HashTable 에 저장이 된다. 또한 해쉬맵에서 어떤 key 를 사용하여 value 를 찾으로고 할 경우에도, 주어진 key 를 사용하여 해쉬값을 계산하여 이를 바탕으로 원소를 찾게 된다.
그런데 현재 상황은
- 넣을 때 key 는 (cash = 5) 인데, 찾을 때는 (cash = 10 ) 인 애로 찾으려고 하다보니, 당연히 찾고자 하는 value 를 찾을 수가 없는 것이다.
생각해보니, 다시 put 을 함으로서 이제는 ten 이 안나온다..🥲ㅋㅋㅋ 조심하자
'책' 카테고리의 다른 글
[Atomic Kotlin] ch03 사용성 : 30 ~ 32 까지 (when 전) (2) | 2023.10.17 |
---|