Лямбда-выражения скомпилированы в синтетические c методы с неопределенным именем. Могут быть и другие неуказанные тонкости, например порядок аргументов метода для захваченных переменных. Кроме того, когда лямбда-выражение обращается к экземпляру this
, есть две опции: скомпилировать его с методом экземпляра или скомпилировать с методом static
, получая экземпляр как обычный параметр.
Для получающегося в результате Поведение лямбда-выражения, это не имеет значения. Но сериализованная форма зависит от этих деталей и, следовательно, очень fr agile. Вам даже не нужно менять класс, перекомпиляция его с другим компилятором может изменить эти детали. Фактически, даже перекомпиляция с одним и тем же компилятором может изменить результат, например, когда поведение компилятора зависит от некоторой карты ha sh с рандомизацией порядка итераций.
На практике поставщики компиляторов пытаются уменьшить такие эффекты и производят стабильные результаты, даже если это не указано в спецификации. Но когда вы меняете класс, все ставки отменяются. Один аспект, который вы можете легко увидеть в скомпилированном файле класса, заключается в том, что компиляторы добавляют число к имени метода в зависимости от порядка вхождения в исходном файле. Вставка другого лямбда-выражения или удаление одного может изменить номера всех последующих лямбда-выражений.
Таким образом, измененный класс A
может быть несовместим с вашим сериализованным лямбда-выражением, и лучшая вещь Это может произойти, это исключение во время десериализации из-за несоответствия. Хуже того, он мог выбрать неправильное лямбда-выражение, потому что у него оказалось совместимое сочетание имени и подписи.
Более безопасная конструкция - это ссылки на метод, поскольку они ссылаются на фактический целевой метод, который не является подвержены влиянию других лямбда-выражений или ссылок на методы в том же классе. Однако не каждая ссылка на метод компилируется как прямая ссылка на уровне байтового кода. В некоторых случаях, например при обращении к методу varargs или к вызову метода super
или метода типа пересечения, класс объявления которого не соответствует стертому типу, компилятор может сгенерировать метод-заглушку для вызова, подобный лямбде выражение. Так что вы все равно должны быть осторожны.