가변객체의 위험성 -> 식별자 가변성

말그대로 식별자로서 사용되는 객체가 (가변객체이기 때문에) 변경되는 것이 허용되어있게 되는 것이고 , 이로 인해 예측하지 못한 일들이 벌어진다는 것이다. 

 

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
복사했습니다!