Оператор двойной двоеточия в Java 8
1. обзор
В этой быстрой статье мы обсудимdouble colon operator (::) в Java 8 и рассмотрим сценарии, в которых можно использовать оператор.
Дальнейшее чтение:
Java 8 Интервью Вопросы (+ ответы)
Набор популярных вопросов об интервью, связанных с Java8, и, конечно, ответов.
Руководство по Java 8 Необязательно
Краткое и практическое руководство по дополнительному в Java 8
Новые функции в Java 8
Краткое введение в новые функции Java 8; основное внимание уделяется стандартным и статическим интерфейсным методам, статическим ссылкам на методы и необязательным.
2. От лямбд к оператору двойного двоеточия
Мы увидели, что с помощью лямбда-выражений код может стать очень кратким.
Например, дляcreate a comparator достаточно следующего синтаксиса:
Comparator c = (Computer c1, Computer c2) -> c1.getAge().compareTo(c2.getAge());
Затем с выводом типа:
Comparator c = (c1, c2) -> c1.getAge().compareTo(c2.getAge());
Но можем ли мы сделать приведенный выше код еще более выразительным и читабельным? Давайте посмотрим:
Comparator c = Comparator.comparing(Computer::getAge);
Мы использовали оператор:: как сокращение для лямбда-выражений, вызывающих определенный метод - по имени. И, наконец, результат - конечно, еще более читаемый синтаксис.
3. Как это работает?
Проще говоря, когда мы используем ссылку на метод - целевая ссылка помещается перед разделителем::, а имя метода указывается после него.
Например:
Computer::getAge;
Мы рассматриваем ссылку на методgetAge, определенный в классеComputer.
Затем мы можем работать с этой функцией:
Function getAge = Computer::getAge;
Integer computerAge = getAge.apply(c1);
Обратите внимание, что мы ссылаемся на функцию, а затем применяем ее к нужному типу аргумента.
4. Ссылки на метод
Мы можем эффективно использовать этот оператор в некоторых сценариях.
4.1. Статический метод
Во-первых, мы собираемся использоватьa static utility method:
List inventory = Arrays.asList(
new Computer( 2015, "white", 35), new Computer(2009, "black", 65));
inventory.forEach(ComputerUtils::repair);
4.2. Метод экземпляра существующего объекта
Затем давайте посмотрим на интересный сценарий -referencing a method of an existing object instance.
Мы собираемся использовать переменнуюSystem.out - объект типаPrintStream, который поддерживает методprint:
Computer c1 = new Computer(2015, "white");
Computer c2 = new Computer(2009, "black");
Computer c3 = new Computer(2014, "black");
Arrays.asList(c1, c2, c3).forEach(System.out::print);
4.3. Метод экземпляра произвольного объекта определенного типа
Computer c1 = new Computer(2015, "white", 100);
Computer c2 = new MacbookPro(2009, "black", 100);
List inventory = Arrays.asList(c1, c2);
inventory.forEach(Computer::turnOnPc);
Как видите, мы ссылаемся на методturnOnPc не на конкретный экземпляр, а на сам тип.
В строке 4 метод экземпляраturnOnPc будет вызываться для каждого объектаinventory.
И это, естественно, означает, что - дляc1 методturnOnPc будет вызываться в экземпляреComputer, а дляc2 - в экземпляреMacbookPro.
4.4. Супер метод конкретного объекта
Предположим, у вас есть следующий метод в суперклассеComputer:
public Double calculateValue(Double initialValue) {
return initialValue/1.50;
}
и этот в подклассеMacbookPro:
@Override
public Double calculateValue(Double initialValue){
Function function = super::calculateValue;
Double pcValue = function.apply(initialValue);
return pcValue + (initialValue/10) ;
}
Вызов методаcalculateValue в экземпляреMacbookPro:
macbookPro.calculateValue(999.99);
также вызоветcalculateValue суперклассаComputer.
5. Ссылки на конструктор
5.1. Создать новый экземпляр
Ссылка на конструктор для создания экземпляра объекта может быть довольно простой:
@FunctionalInterface
public interface InterfaceComputer {
Computer create();
}
InterfaceComputer c = Computer::new;
Computer computer = c.create();
Что если у вас есть два параметра в конструкторе?
BiFunction c4Function = Computer::new;
Computer c4 = c4Function.apply(2013, "white");
Если параметров три или более, вы должны определить новый функциональный интерфейс:
Затем инициализируйте ваш объект:
TriFunction c6Function = Computer::new;
Computer c3 = c6Function.apply(2008, "black", 90);
5.2. Создать массив
Наконец, давайте посмотрим, как создать массив объектовComputer с пятью элементами:
Function computerCreator = Computer[]::new;
Computer[] computerArray = computerCreator.apply(5);
6. Заключение
Как мы начинаем видеть, оператор двойного двоеточия, представленный в Java 8, будет очень полезен в некоторых сценариях, особенно в сочетании с Streams.
Также очень важно взглянуть на функциональные интерфейсы, чтобы лучше понять, что происходит за кулисами.
Полныйsource code для примера доступен вthis GitHub project - это проект Maven и Eclipse, поэтому его можно импортировать и использовать как есть.