Ссылки на конструкторы
Используйте ClassName::new для создания экземпляров через функциональные интерфейсы, такие как Supplier и Function.
«Ссылки на конструкторы» — бесплатный урок Java Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.
Что такое ссылки на конструкторы
Ссылка на конструктор использует ClassName::new для создания объектов через функциональный интерфейс. Параметры функционального интерфейса соответствуют параметрам конструктора.
import java.util.function.*;
class Person {
String name;
Person(String name) { this.name = name; }
public String toString() { return "Person(" + name + ")"; }
}
// Function<String, Person> — calls Person(String)
Function<String, Person> factory = Person::new;
Person p = factory.apply("Alice");
System.out.println(p); // Person(Alice)Конструктор без аргументов как Supplier
Конструктор без аргументов соответствует Supplier<T>:
class Counter {
int count = 0;
void inc() { count++; }
}
Supplier<Counter> newCounter = Counter::new;
Counter c1 = newCounter.get();
Counter c2 = newCounter.get(); // independent instances
c1.inc();
System.out.println(c1.count); // 1
System.out.println(c2.count); // 0Конструктор с двумя аргументами как BiFunction
Конструкторы с двумя параметрами соответствуют BiFunction<T,U,R>:
record Point(int x, int y) {}
BiFunction<Integer, Integer, Point> makePoint = Point::new;
Point p = makePoint.apply(3, 4);
System.out.println(p); // Point[x=3, y=4]Ссылка на конструктор в Stream.map
Преобразуйте строки в объекты с помощью ссылки на конструктор:
import java.util.*;
import java.util.stream.*;
List<String> names = List.of("Alice","Bob","Carol");
List<Person> people = names.stream()
.map(Person::new) // calls new Person(name) for each
.collect(Collectors.toList());
people.forEach(System.out::println);
// Person(Alice)
// Person(Bob)
// Person(Carol)Ссылка на конструктор массива
Создавайте массивы динамически с помощью Type[]::new. Это используется в Stream.toArray():
import java.util.stream.*;
String[] arr = Stream.of("a","b","c")
.toArray(String[]::new);
for (String s : arr) System.out.print(s + " ");
// a b c
int[] sizes = {3, 5, 2};
String[][] matrix = Arrays.stream(sizes)
.mapToObj(String[]::new)
.toArray(String[][]::new);Шаблон интерфейса Factory
Определите пользовательский функциональный интерфейс для фабрик, а затем используйте ссылки на конструкторы:
@FunctionalInterface
interface Factory<T> {
T create(String config);
}
class DBConnection {
String url;
DBConnection(String url) { this.url = url; }
public String toString() { return "DB(" + url + ")"; }
}
Factory<DBConnection> dbFactory = DBConnection::new;
DBConnection conn = dbFactory.create("jdbc:postgresql://localhost/mydb");
System.out.println(conn);Внедрение зависимостей со ссылками на конструкторы
Фреймворки часто используют функциональные фабрики для отложенного создания экземпляров. Ссылки на конструкторы делают этот шаблон понятным:
import java.util.function.*;
class ServiceLocator {
private final Map<String, Supplier<?>> registry = new HashMap<>();
<T> void register(String name, Supplier<T> factory) {
registry.put(name, factory);
}
@SuppressWarnings("unchecked")
<T> T get(String name) { return (T) registry.get(name).get(); }
}
ServiceLocator loc = new ServiceLocator();
loc.register("counter", Counter::new);
Counter c = loc.get("counter");Выбор между лямбдой и ссылкой на конструктор
Используйте ссылку на конструктор, если тело лямбды представляет собой только new Type(args):
// Lambda:
Function<String, Person> f1 = name -> new Person(name);
// Constructor reference (preferred):
Function<String, Person> f2 = Person::new;
// When you need extra logic, stick with lambda:
Function<String, Person> f3 = name -> new Person(name.trim().toLowerCase());Обобщённые типы и ссылки на конструкторы
Обобщённые классы также поддерживаются — тип выводится из контекста функционального интерфейса:
import java.util.*;
import java.util.function.*;
// ArrayList::new matches Supplier<ArrayList<String>>
Supplier<List<String>> listFactory = ArrayList::new;
List<String> l1 = listFactory.get();
List<String> l2 = listFactory.get(); // independent lists
l1.add("hello");
System.out.println(l2.size()); // 0Коллекторы потоков со ссылками на конструкторы
Используйте ссылки на конструкторы в коллекторах для создания пользовательских контейнеров результатов:
import java.util.stream.*;
// Collect into a LinkedList using a constructor reference supplier
LinkedList<String> linked = Stream.of("a","b","c")
.collect(Collectors.toCollection(LinkedList::new));
System.out.println(linked.getFirst()); // aПримитивы и автоматическая упаковка
Ссылки на конструкторы типов-обёрток поддерживают автоматическую упаковку:
// Integer::new is deprecated in Java 9+, but illustrates the concept
// Use Integer.valueOf or just autoboxing in modern Java
Function<String, Integer> intParser = Integer::parseInt; // static method ref
System.out.println(intParser.apply("42")); // 42Быстрая проверка
Какому функциональному интерфейсу соответствует ссылка на конструктор без аргументов, например ArrayList::new?
Итоги: ссылки на конструкторы
Основные выводы:
- Синтаксис: ClassName::new — делегирует вызов подходящему конструктору
- Без аргументов → Supplier<T>; один аргумент → Function<T,R>; два аргумента → BiFunction
- Конструктор массива: Type[]::new — используется с Stream.toArray()
- Чище, чем лямбда, когда тело лямбды представляет собой только 'new Type(args)'
- Используйте Collectors.toCollection(LinkedList::new) для типизированных результатов-коллекций
Часто задаваемые вопросы
Урок «Ссылки на конструкторы» бесплатный?
Да — полный текст урока «Ссылки на конструкторы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.
Чему я научусь в уроке «Ссылки на конструкторы»?
Используйте ClassName::new для создания экземпляров через функциональные интерфейсы, такие как Supplier и Function. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Java Academy?
Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Ссылки на конструкторы»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Java Academy?
Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Ссылки на статические методы
- Ссылки на методы экземпляра конкретного объекта
- Ссылки на методы произвольного экземпляра
- Ссылки на конструкторы