Biorąc pod uwagę następujący kod:
public static void main(String[] args) {
record Foo(int[] ints){}
var ints = new int[]{1, 2};
var foo = new Foo(ints);
System.out.println(foo); // Foo[ints=[I@6433a2]
System.out.println(new Foo(new int[]{1,2}).equals(new Foo(new int[]{1,2}))); // false
System.out.println(new Foo(ints).equals(new Foo(ints))); //true
System.out.println(foo.equals(foo)); // true
}
Wydaje się, oczywiście, na tej tablicy toString
, equals
sposoby są stosowane (zamiast metod statycznych Arrays::equals
, Arrays::deepEquals
bądź Array::toString
).
Sądzę więc, że Java 14 Records ( JEP 359 ) nie działa zbyt dobrze z tablicami, odpowiednie metody muszą zostać wygenerowane za pomocą IDE (które przynajmniej w IntelliJ domyślnie generuje „przydatne” metody, tj. Używają metod statycznych w Arrays
).
Czy jest jakieś inne rozwiązanie?
toString()
, equals()
oraz hashCode()
sposoby zapisu są realizowane przy użyciu invokedynamic odniesienia. . Gdyby tylko skompilowany ekwiwalent klasy mógł być bliższy temu, co Arrays.deepToString
robi dziś metoda w swojej prywatnej, przeciążonej metodzie, mógłby rozwiązać problem pierwotnych przypadków.
Object
, ponieważ może się to zdarzyć również w przypadku klas zdefiniowanych przez użytkownika. np. niepoprawny równa się
invokedynamic
nie ma absolutnie nic wspólnego z wyborem semantyki; indy jest tutaj czystym szczegółem implementacji. Kompilator mógł wysłać kod bajtowy, aby zrobić to samo; był to po prostu bardziej wydajny i elastyczny sposób dotarcia do celu. Podczas projektowania rekordów szeroko dyskutowano, czy należy stosować bardziej szczegółową semantykę równości (np. Głęboką równość dla tablic), ale okazało się, że powoduje to o wiele więcej problemów, niż przypuszczalnie rozwiązano.
List
zamiast tablicy?