@ramazan793

Оператор двоеточия (::) java, какой принцип работы?

Обычная лямбда функция a -> foo(a) работает понятно и логично, в отличие от оператора двоеточия. Вот два примера:
1 пример:
// с использованием ::
list.forEach(System.out::println); 
// то же самое, но обычной лямбдой
list.forEach(n -> System.out.println(n));

Исходя из этого примера, можно сказать, что (::) принимает только один аргумент и автоматически подставляет его в функции println класса System.out.
А теперь 2 пример:
map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey);
// Исходя из логики первого примера, эквивалентно, используя лямбду, можно было бы заменить так:
map.entrySet().stream().collect(Collectors.toMap(a -> Map.Entry.getKey(a)); // однако очевидно, что это неправильно, и правильно будет так:
map.entrySet().stream().collect(Collectors.toMap(a -> a.getKey());

Отсюда вопросы:
как :: определяет, как именно необходимо вызывать метод(System.out.println(n) или n.getKey() )?
как :: может работать с несколькими аргументами?
какой у него вообще принцип работы?
  • Вопрос задан
  • 15128 просмотров
Решения вопроса 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Java
Седой и строгий
Прежде всего, квадраточие - это оператор, а не функция. Поэтому никаких аргументов он не принимает. У него есть левая часть выражения и правая часть выражения, как у оператора точка, например. Оператор точка позволяет получить значение поля, указанного в правой части выражения, класса, указанного в левой - SomeClass.someField Так же и квадроточие позволяет получить ссылку на метод, указанный в правой части, класса, указанного в левой.

Компилятор выводит тип ссылки из контекста и приводит её к соответствующему функциональному интерфейсу. В частности метод forEach принимает Consumer<? super T>, к нему и будет приведена ссылка на метод println, возвращаемая выражением System.out::println

На уровне виртуальной машины, как ссылки на методы, так и лямбды - это создаваемые в рантайме прокси-классы. Пример их генерации и композиции вы можете увидеть здесь.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Это ссылка на метод. Ссылку можно получить на метод с любым количеством параметров.

Но подставить ее можно только туда, где она подойдёт по типу.
Ответ написан
Комментировать
DanielDemidko
@DanielDemidko
Программист
:: Никуда ничего не подставляет. Это значит что вы берете и отправляете САМ метод println вместо лямбды
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы