← Назад к вопросам
Что может находиться слева от оператора ::
2.0 Middle🔥 171 комментариев
#Stream API и функциональное программирование#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Оператор :: (method reference) имеет разные формы слева
Оператор :: (method reference) — это синтаксический сахар для создания ссылок на методы (Java 8+). Слева от :: может стоять несколько вариантов.
1. Имя класса (статический метод)
Основная форма — вызов статического метода класса:
public class Calculator {
public static int add(int a, int b) {
return a + b;
}
public static int multiply(int a, int b) {
return a * b;
}
}
public class Demo {
public static void main(String[] args) {
// Ссылка на статический метод
// ClassName::methodName
// Пример 1: Ссылка на add
java.util.function.BiFunction<Integer, Integer, Integer> adder =
Calculator::add;
int result = adder.apply(5, 3); // Вызов через интерфейс
System.out.println("Результат: " + result); // 8
// Пример 2: В Stream API
List<int[]> pairs = Arrays.asList(
new int[]{1, 2},
new int[]{3, 4}
);
pairs.forEach(pair -> {
System.out.println(Calculator::add.apply(pair[0], pair[1]));
});
}
}
2. Переменная объекта (метод экземпляра)
Ссылка на метод конкретного объекта:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String greet() {
return "Привет, я " + name;
}
public String greetWith(String greeting) {
return greeting + ", " + name;
}
}
public class Demo {
public static void main(String[] args) {
// object::methodName
Person person = new Person("Алиса");
// Ссылка на метод конкретного объекта
java.util.function.Supplier<String> greeter = person::greet;
System.out.println(greeter.get()); // "Привет, я Алиса"
// С параметром
java.util.function.Function<String, String> greetWithFunc =
person::greetWith;
System.out.println(greetWithFunc.apply("Привет"));
// "Привет, Алиса"
// В Stream API
List<String> messages = Arrays.asList(
"Hello",
"Hi",
"Hey"
);
messages.forEach(msg -> System.out.println(greetWithFunc.apply(msg)));
}
}
3. Класс (конструктор)
Ссылка на конструктор класса:
public class User {
private String username;
public User(String username) {
this.username = username;
}
@Override
public String toString() {
return "User{" + username + "}";
}
}
public class Demo {
public static void main(String[] args) {
// ClassName::new
// Ссылка на конструктор
java.util.function.Function<String, User> userFactory = User::new;
User user1 = userFactory.apply("alice");
User user2 = userFactory.apply("bob");
System.out.println(user1); // User{alice}
System.out.println(user2); // User{bob}
// В Stream API
List<String> names = Arrays.asList("charlie", "diana", "eve");
List<User> users = names.stream()
.map(User::new) // Создаём User из каждого имени
.collect(Collectors.toList());
System.out.println(users);
// [User{charlie}, User{diana}, User{eve}]
}
}
4. Тип (метод экземпляра любого объекта этого типа)
Ссылка на метод, который вызывается на любом объекте типа:
public class StringUtils {
public static void main(String[] args) {
// Type::methodName
// Первый параметр становится объектом, на котором вызывается метод
// Пример 1: Метод String::toUpperCase()
java.util.function.Function<String, String> toUpper = String::toUpperCase;
System.out.println(toUpper.apply("hello")); // "HELLO"
// Пример 2: В Stream API
List<String> words = Arrays.asList("apple", "banana", "cherry");
words.stream()
.map(String::toUpperCase) // Вызывает toUpperCase на каждой строке
.forEach(System.out::println);
// APPLE
// BANANA
// CHERRY
// Пример 3: Метод с параметром
java.util.function.BiFunction<String, String, Boolean> contains =
String::contains;
boolean result = contains.apply("hello world", "world"); // true
System.out.println(result);
// Пример 4: Используется как Comparator
List<String> names = Arrays.asList("Bob", "Alice", "Charlie");
names.sort(String::compareTo); // Сортировка по алфавиту
System.out.println(names); // [Alice, Bob, Charlie]
}
}
5. super (метод суперкласса)
Ссылка на переопределённый метод суперкласса:
public class Parent {
public String describe() {
return "Я родитель";
}
}
public class Child extends Parent {
@Override
public String describe() {
return "Я ребёнок";
}
public void testSuper() {
// super::methodName
java.util.function.Supplier<String> parentDescriber = super::describe;
String parentDescription = parentDescriber.get();
System.out.println(parentDescription); // "Я родитель"
}
}
public class Demo {
public static void main(String[] args) {
Child child = new Child();
child.testSuper();
}
}
6. this (текущий объект)
Ссылка на метод текущего объекта:
public class Service {
private String name;
public Service(String name) {
this.name = name;
}
public void doWork() {
System.out.println(name + " работает");
}
public void executeTask() {
// this::methodName
java.util.function.Consumer<Service> worker = s -> s.doWork();
// Или напрямую через this
java.util.function.Runnable task = this::doWork;
task.run(); // Вызовет doWork() на текущем объекте
}
}
Полная таблица синтаксиса method reference
| Форма | Синтаксис | Пример | Тип |
|---|---|---|---|
| Статический метод | Class::staticMethod | Math::max | Reference to a static method |
| Метод экземпляра (конкретный объект) | object::instanceMethod | person::greet | Reference to an instance method of a particular object |
| Метод экземпляра (любой объект типа) | Class::instanceMethod | String::toUpperCase | Reference to an instance method of an arbitrary object of a particular type |
| Конструктор | Class::new | User::new | Reference to a constructor |
| Super метод | super::method | super::describe | Reference to a supertype method |
| This метод | this::method | this::doWork | Reference to a current object method |
Практические примеры в Stream API
public class StreamExamples {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
// 1. Метод класса (статический)
System.out.println("Использование Integer::parseInt");
List<Integer> numbers = Arrays.asList("1", "2", "3");
numbers.stream()
.map(Integer::parseInt) // Integer::parseInt
.forEach(System.out::println);
// 2. Метод типа
System.out.println("\nИспользование String::toUpperCase");
fruits.stream()
.map(String::toUpperCase) // String::toUpperCase
.forEach(System.out::println);
// 3. Конструктор
System.out.println("\nИспользование ArrayList::new");
fruits.stream()
.collect(Collectors.toCollection(ArrayList::new)) // ArrayList::new
.forEach(System.out::println);
// 4. System.out::println
System.out.println("\nИспользование System.out::println");
fruits.forEach(System.out::println); // object::method
// 5. Сортировка с помощью method reference
System.out.println("\nСортировка");
fruits.stream()
.sorted(String::compareTo) // Type::method
.forEach(System.out::println);
}
}
Сравнение: Lambda vs Method Reference
// Lambda версия
Function<String, String> lambda = s -> s.toUpperCase();
// Method reference версия
Function<String, String> reference = String::toUpperCase;
// Обе работают одинаково, но reference читается понятнее
Вывод
Слева от :: может стоять:
- Имя класса — для статических методов (
Calculator::add) - Переменная объекта — для методов конкретного объекта (
person::greet) - Имя типа — для методов типа (
String::toUpperCase) - Конструктор класса —
ClassName::new(User::new) - super — для методов суперкласса (
super::method) - this — для методов текущего объекта (
this::method)
Это мощный синтаксический сахар для функционального программирования в Java, широко используется в Stream API и lambda выражениях.