Разница между операторами : и :: в Java
Два вопроса по операторам java:
- В чем отличие действия операторов двоеточие
:
и квадроточие::
? - Как создать массив и
List
, используя квадроточие типаArrayList::new
иint[]::new
?
Ответы (2 шт):
В чем отличие действия операторов "двоеточие"
:
и "квадроточие"::
?
Звучит примерно как "В чём разница между Spring и String?". Это просто два совершенно разных оператора. Двоеточие используется, например, в тернарных операторах
int a = b > c ? 10 : 20;
или при написании цикла в стиле foreach
for (String each : List<String>) {...}
Может быть, ещё где-то, но мне с ходу вспомнились эти два случая.
"Квадроточие" же чаще всего называют ссылкой на метод (method reference) - это сокращённая форма записи лямбда-выражения и, соответственно, она используется только применительно к лямбдам.
Как создать массив и List используя квадроточие типа
ArrayList::new
иint[]::new
?
Их можно создать в контексте функционального интерфейса Supplier<T>
. Вот пример для ArrayList
:
List<String> list = ... // есть какой-то список
list
.stream()
. // что-то с ним делаем
.collect(Collectors.toCollection(ArrayList::new));
1. В чем отличие действия операторов двоеточие (:) и квадроточие (::)?
В Java символ :
используется в разных местах:
- Как часть тернарного логического оператора
?:
, возвращающего одно из двух значений:
String message = age < 16 ? "Детям вход воспрещён" : "Добро пожаловать!";
- В сокращенной конструкции для цикла
for-each
(Java 5+).
Фактически этот цикл представляет собой синтаксический сахар для итерации по массивам или объектам, реализующий интерфейсIterable
, т.е. к коллекциям, спискам, сетам (множествам) и т.д.
for (Type Identifier : Expression) Statement
При этом для массивов цикл for-each
преобразуется в классический цикл for
со счётчиком:
T[] a = Expression;
for (int i = 0; i < a.length; i++) {
Type Identifier = a[i];
Statement
}
А для Iterable
объектов используется итератор и его методы:
for (I iter = Expression.iterator(); iter.hasNext(); ) {
Type Identifier = iter.next();
Statement
}
- После меток для передачи управления во вложенных циклах:
int[] arr = {1, 2, 3, 4, 5};
out: for (int x : arr) {
for (int i = 0; i < x; i++) {
if (foo(x, i)) {
continue out;
} else if (bar(i)) {
break out;
}
}
}
- После меток
case
в классической форме оператораswitch
:
enum Weekday(MON, TUE, WED, THU, FRI, SAT, SUN);
// ...
public String getDesc(Weekday wd) {
switch (wd) {
case SAT: case SUN:
return "Week-end";
case MON:
return "Manic Monday";
case WED:
return "Mini Friday";
case FRI:
return "Party time!";
default:
return "Workday";
}
}
- После условий в ассертах (assert) для вывода соответствующих сообщений:
int x = -1;
assert x >= 0: "Negative x";
"Квадроточие" представляет собой ссылку на метод (Method Reference), добавленную в Java 8 вместе с другими фичами для программирования в функциональном стиле такими как лямбда-выражения, функциональные интерфейсы и т.д., см. похожий вопрос Что значит оператор ::
?.
Официальная документация от Oracle: Method References
Ссылки на метод можно рассматривать как некий более эффективный и читабельный аналог лямбда-выражений.
2. Как создать массив и
List
, используя квадроточие типаArrayList::new
иint[]::new
?
Ссылки на конструкторы можно рассматривать как реализации соответствующих интерфейсов Supplier
, IntFunction
и др.:
Supplier<List<String>> defaultList = ArrayList::new; // ссылка на дефолтный конструктор
IntFunction<List<String>> capacityList = ArrayList::new; // ссылка на конструктор с capacity
IntFunction<int[]> arrayFactory = int[]::new;
List<String> list1 = defaultList.get(); // список по умолчанию
List<String> list2 = capacityList.apply(20); // список с емкостью 20
int[] arr = arrayFactory.apply(10); // массив из 10 элементов