IntelliJ IDEA предлагает заменить лямбда-выражения ссылками на методы. В чём разница разница между ними?
Принципиальная разница вот в чём: лямбда - это всегда новый метод в классе. Если декомпилировать вот такой код:
Function<String, String> f = s -> s.toUpperCase();
f.apply("abc");
получим такой байткод:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
// байткод main
private static java.lang.String lambda$main$0(java.lang.String);
descriptor: (Ljava/lang/String;)Ljava/lang/String;
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
// байткод лямбды
Для сравнения, код со ссылкой на метод:
Function<String, String> f = String::toUpperCase;
f.apply("abc");
даст такой байткод:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
// байткод main
Каждая лямбда в байткоде превращается в приватный синтетический метод с именем вроде lambda$0
, который будет вызываться через invokedynamic
каждый раз, когда нужна лямбда. Поэтому IDEA и советует вам заменить лямбду на ссылку на метод - так байткод класса будет компактнее, а значит, класс быстрее загрузится в JVM. Само собой, для того чтобы ощутить такой прирост, нужны тысячи неоптимизированных лямбд, но в крупном проекте такое количество наберётся легко.
В остальном выбор между лямбдой и ссылкой на метод - вопрос вкуса и читаемости кода. Например, если в лямбде несколько строк, читаемость снижается, и код только выиграет, если лямбду вынести в отдельный метод, и использовать ссылку на него. Или, например, если есть класс ClassWithVeryVeryVeryLongName
с методом doSth()
, то лямбда c -> c.doSth()
будет читаться проще, чем ClassWithVeryVeryVeryLongName::doSth
.
В лямбде вы вызываете метод, который принимает столько параметров сколько у лямбды с теми же типами. Поэтому его можно заменить ссылкой на метод, которая в свою очередь тоже является лямбдой.
Об этом более или менее подробно описано в примере:
Arrays.sort(rosterAsArray,
(a, b) -> Person.compareByAge(a, b)
);
Поскольку это лямбда-выражение вызывает существующий метод, вы можете использовать ссылку на метод вместо выражения лямбда:
Arrays.sort(rosterAsArray, Person::compareByAge);
Ссылка метода Person::compareByAge
семантически совпадает с
выражением лямбда (a, b) -> Person.compareByAge(a, b)
. Каждый из
них имеет следующие характеристики:
Comparator<Person>.compare
, который является (Person, Person)
. Person.compareByAge
.Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Перепробовал разные методыОшибок подключения к базе вроде нет
Возможно ли соединить два(или больше) видео так, что бы они имели общий TimeBar(длина была в длину обеих видио, и пользователь мог менять позицию)В...
Есть окно, там находятся две кнопки, одна Войти, другая Регистрация, по нажатию любой из них у меня открывается новое свое окно, проблема именно...