← Назад к вопросам

Что может находиться слева от оператора ::

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::staticMethodMath::maxReference to a static method
Метод экземпляра (конкретный объект)object::instanceMethodperson::greetReference to an instance method of a particular object
Метод экземпляра (любой объект типа)Class::instanceMethodString::toUpperCaseReference to an instance method of an arbitrary object of a particular type
КонструкторClass::newUser::newReference to a constructor
Super методsuper::methodsuper::describeReference to a supertype method
This методthis::methodthis::doWorkReference 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 читается понятнее

Вывод

Слева от :: может стоять:

  1. Имя класса — для статических методов (Calculator::add)
  2. Переменная объекта — для методов конкретного объекта (person::greet)
  3. Имя типа — для методов типа (String::toUpperCase)
  4. Конструктор классаClassName::new (User::new)
  5. super — для методов суперкласса (super::method)
  6. this — для методов текущего объекта (this::method)

Это мощный синтаксический сахар для функционального программирования в Java, широко используется в Stream API и lambda выражениях.