Разница между операторами : и :: в Java

Два вопроса по операторам java:

  1. В чем отличие действия операторов двоеточие : и квадроточие ::?
  2. Как создать массив и List, используя квадроточие типа ArrayList::new и int[]::new?

Ответы (2 шт):

Автор решения: Byb

В чем отличие действия операторов "двоеточие" : и "квадроточие" ::?

Звучит примерно как "В чём разница между 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));
→ Ссылка
Автор решения: Nowhere Man

1. В чем отличие действия операторов двоеточие (:) и квадроточие (::)?

В Java символ : используется в разных местах:

  1. Как часть тернарного логического оператора ?:, возвращающего одно из двух значений:
String message = age < 16 ? "Детям вход воспрещён" : "Добро пожаловать!";
  1. В сокращенной конструкции для цикла 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
}
  1. После меток для передачи управления во вложенных циклах:
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;
        }
    }
}
  1. После меток 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";
    }
}
  1. После условий в ассертах (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 элементов
→ Ссылка