String.hashCode는 같은 문자열이지만 때로는 다른 값으로 바뀔 수 있습니다
Fluter/Dart에서 프로그램을 개발할 때 맵에서 '같은 문자열이 다른 키로 들어오는 것' 현상을 만났습니다.더 조사해 보면 같은 문자열
String.hashCode
이 다른 이유가 무엇인지 알 수 있다.이것저것 여러 가지 이유로 Dart의 가장자리를 밟는 버그가 겹쳤지만 upstream에서 해결됐다.
대략적 실현
문자열을 처리하고 반환할 수 있는 함수는 다음과 같습니다.
String foo(String name) {
return "prefix-${name}";
}
Map에 데이터를 넣는 프로세스:Map data = new Map<String, String>();
String str1 = foo("test");
// ...
// str1 は "prefix-test" という文字列
data[str1] = "value";
Map에서 데이터를 체크 아웃하는 프로세스:String str2 = foo("test");
// str2 は "prefix-test" という文字列
// str1 と同じ
String value = data[str2];
// "value" を期待するが null になる
print(value);
위에서 말한 바와 같이 Map
에 대해'동일 문자열'을 사용하여 접근했지만 예상대로 처리되지 않았다.hashCode
Map
대상의 hashCode
를 사용하여 저장 위치를 제어한다(여러 언어가 이렇게 이루어졌기 때문에 Dart도 그렇다고 생각한다). 그래서 hashCode
는 이상하다. 그래서 다음과 같이'같은 문자열, 다르다hashCode
'를 확인했다.print("${str1 == str2}"); // true
print("${str1.hashCode == str2.hashCode}"); // false!!!
통상적인Object.hashCode
은'동일성을 나타내는 것'을 토대로 계산된 것이다.이런 상황에서 같은 점은 메모리의 주소도 같다는 점이다.그러나
String
,Point
,Rect
같은 클래스에서 같은 값이면 같은 값==
이 되돌아와true
하면 같은 값hashCode
으로 처리할 수 있다.따라서 다른 곳에서 생성된 대상==
이라도 같은 키String
로 사용할 수 있다.이번 문제는 어떤 이유로 같은 값Map
이 다른 값String
으로 바뀌었기 때문이다.또 이런 현상은 iOS 시뮬레이터 및 실제 기기에서만 발생하며, 안드로이드 시뮬레이터 및 실제 기기에서는 일어나지 않는다.
identityHashCode
상기 코드에서 생략된 부분은 문자열
hashCode
에 대한 호출str1
의 코드가 있다.호출identityHashCode
이 변경identityHashCode
의 원인이다.identity HashCode란 무엇입니까?
Returns the identity hash code of
hashCode
.Returns the same value as
object
if [object] has not overridden[Object.hashCode]. Returns the value that [Object.hashCode] would return
on this object, even if
object.hashCode
has been overridden.This hash code is compatible with [identical].
덮어쓰기
hashCode
의 클래스 대상에 대해서도 기본 클래스hashCode
의 값을 얻을 수 있는 함수다.등치라도 다른 대상이라면 다른 대상으로 처리할 때 이 함수Object.hashCode
또는identityHashCode
를 사용한다.그러나 이 함수 내부 호출
identical
의 값으로 Object.hashCode
의 결과도 캐시되었다.String.hashCode
의 계산은 어느 정도의 원가가 필요하기 때문에 계산된 물건은 캐시hashCode
가 필요하다면 문제가 된다.일반적으로 코드를 쓰면
String
사용하지 않기 때문에 대부분의 응용 프로그램은 문제가 없을 것이라고 생각합니다.대책
identityHashCode
는 더 이상 사용하지 않습니다.이 함수를 사용하지 않아도 가능한 코드는 동일성이라기보다는'동일 여부'를 기반으로 처리돼 이렇게 수정됐다.어쨌든 Flutter가 사용하는Dart의 버전이 상승하고 그에 상응하는 수정이 포함되며 그 전에 대응해야 할 경우 코드를 다시 수정할 수 있다.
덤
원인을 규명하기 전에 시도해 본 일
Reference
이 문제에 관하여(String.hashCode는 같은 문자열이지만 때로는 다른 값으로 바뀔 수 있습니다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/najeira/articles/2018-08-02-qiita-3558680224c8f226a4b7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)