W czasie moich wykładów, gdy opowiadałem o rekordach w Javie, wielokrotnie padało pytanie: “czy hashCode() w rekordach jest jakoś cache’owany?”. Sprawdźmy to ;-)
W zasadzie, jeżeli jesteś już po lekturze mojego poprzedniego wpisu o metodach equals() i hashCode() w rekordach, prawdopodobnie znasz już odpowiedź. Z racji tego, iż to osobne pytanie, przeprowadźmy osobny eksperyment.
Najpierw zdefiniujmy prostą metodę do odpluskwiania:
Następnie uruchommy ów kod:
Rezultaty, które otrzymuję wykorzystując OpenJDK Runtime Environment (build 16+36-2231) bez żadnych dodatkowych przełączników czy parametrów, są następujące:
1, 1, [] 100603, 100603, [ene] 3218521, 3218521, [ene, due] 103095902, 103095902, [ene, due, like] -1095859017, -1095859017, [ene, due, like, fake]Jeśli u Ciebie pokazały się inne liczby, nie ma co się martwić. Kontrakt hashCode mówi bowiem, iż rezultaty wywołania hashCode() mogą być różne przy każdym uruchomieniu programu napisanego w Javie. Co ma znaczenie, to fakt, iż każda zmiana w komponentach rekordu w ramach jednego uruchomienia programu skutkuje innym hashCodem. Jak napisałem poprzednio, rekordy są niezmienne (ang. immutable), ale jest to niezmienność płytka (ang. shallow immutability).
Odpowiadając na zadane pytanie: choćby jeżeli hashCode() jest jakoś cache’owane, to ten cache wygląda na czyszczony po każdej zmianie ;-)
Poza tym JavaDoc jasno stwierdza: Konkretny algorytm, wykorzystany w skrycie dostarczonej implementacji, jest nieokreślony i jest przedmiotem dalszych zmian w zakresie powyższych ograniczeń. jeżeli ciekawi Cię co to za ograniczenia, RTFM!
Poza tym, by uniknąć niedomówień (niektórzy muszą mieć pewne rzeczy napisane wprost): umieszczanie w rekordach komponentów, które są zmienne, to najprawdopodobniej jeden z tych Całkiem Głupich Pomysłów™. Zalecam zastanowić się przynajmniej dwa razy, zanim napiszesz taki rekord. Tutaj chodzi jedynie o demonstrację.