Комментарии 20
Один больной вопрос, который меня интересует: можно ли создать несколько публичных записей в одном файле?Подскажите, в чем проблема оборачивать в класс, Records.java к примеру?
Интересно, а можно ли использовать рекорды в качестве параметров аннотаций? А то ограничение только скалярами, строками и классами нередко оказывается слишком неудобным.
public class Records {
public static void main(String[] args) {
new Point<Integer>(1, 2).print();
new Point<String>("11", 2).print();
}
}
record Point<T>(T x, int y) {
void print() {
System.out.println("" + x + " - " + y);
}
}
Вопрос к разработчикам: почему внезапно аксессоры компонентов назвали также как и поля, тогда как в джаве стандарт — это getXXX()? Много фреймворков и библиотек настроены работать именно с геттерами...
Каждое нововведение в джаве вызывает смешанные чувства, одновременно и хорошие и плохие.
Что такое Record? Скорее всего это просто класс со всем его поведением, но вводится новое ключевое слово record
и теперь у нас есть и class и record, но пишем мы point.getClass()
… Разве не лучше было бы record class
хотя бы? Когда-нибудь дойдет до структур и получим class, record и struct, угадай что тебе надо.
Хороший вопрос про геттеры и сеттеры, да и многие примеры вызывают один и тот же вопрос, почему сделан такой выбор?
Спасибо за исследование! Это небольшое различие в значениях хеша лишило меня всякого сна и покоя, пришлось лезть разбираться, в чем же тут дело. И разобралось следующее.
Objects.hashCode опирается на алгоритм, приведенный в описании метода java.util.List.hashCode:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode())
Для записей метод расчета хеша генерируется тут: java.lang.runtime.ObjectMethods.makeHashCode(Class<?>, List).
Я выделил самые, на мой взгляд, важные части:
private static int hashCombiner(int x, int y) {
return x*31 + y;
}
private static MethodHandle makeHashCode(Class<?> receiverClass,
List<MethodHandle> getters) {
//метод, всегда возвращающий 0
MethodHandle accumulator = MethodHandles.dropArguments(ZERO, 0, receiverClass);
for (MethodHandle getter : getters) {
//для примитивов hashCode их класса-обертки (Integer, Float и т.д.)
//а для объектов Objects.hashCode
MethodHandle hasher = hasher(getter.type().returnType());
MethodHandle hashThisField = MethodHandles.filterArguments(hasher, 0, getter);
//HASH_COMBINER это ссылка на метод hashCombiner выше
MethodHandle combineHashes = MethodHandles.filterArguments(
HASH_COMBINER, 0, accumulator, hashThisField);
accumulator = MethodHandles.permuteArguments(
combineHashes, accumulator.type(), 0, 0);
}
return accumulator;
}
Если не вдаваться к детали, то получается, что для записей алгоритм расчета хеша идентичен java.util.List.hashCode (тоже хеш элементов считает да на 31 умножает, ага) за исключением инициализации счетчика нулем, а не единицей. Могли бы ради единообразия подхода и тут с единицы считать начинать. Я бы тогда поспал :)
Интересно, будет ли реализации equals()
, созданная вызовом invokedynamic
при исполнении, менять порядок сравнения, чтобы сначала сравнивались примитивные типы, строки и простые объекты?
В текущей реализации всё отдано на откуп компилятору.
В каком порядке он геттеры в статические параметры invokedynamic
загонит, в таком и будут проверяться:
/**
* Generates a method handle for the {@code equals} method for a given data class
* @param receiverClass the data class
* @param getters the list of getters
* @return the method handle
*/
private static MethodHandle makeEquals(Class<?> receiverClass,
List<MethodHandle> getters) {
...
for (MethodHandle getter : getters) {
MethodHandle equalator =
equalator(getter.type().returnType()); // (TT)Z
MethodHandle thisFieldEqual =
MethodHandles.filterArguments(equalator, 0, getter, getter); // (RR)Z
accumulator =
MethodHandles.guardWithTest(
thisFieldEqual, accumulator, instanceFalse.asType(rr)
);
}
return MethodHandles.guardWithTest(
isSameObject,
instanceTrue,
MethodHandles.guardWithTest(isInstance, accumulator.asType(ro), instanceFalse)
);
}
Скорее всего проверки пойдут в порядке декларации полей.
Программист захочет — сам поля в записи переупорядочит.
Исследуем записи в Java 14