Ссылки на методы экземпляра конкретного объекта
Сохраняйте ссылку на конкретный объект и используйте один из его методов экземпляра для обратных вызовов и обработчиков.
«Ссылки на методы экземпляра конкретного объекта» — бесплатный урок Java Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.
Ссылка на конкретный экземпляр
Ссылка на метод экземпляра конкретного объекта сохраняет определённый объект и ссылается на один из его методов. Синтаксис: instance::methodName.
// System.out is a specific PrintStream instance
List<String> names = List.of("Alice","Bob","Carol");
names.forEach(System.out::println); // System.out is the captured instanceСохранение экземпляра пользовательского объекта
Можно сохранить любой объект. Ссылка на метод использует этот экземпляр в момент создания:
class Greeter {
private String prefix;
Greeter(String prefix) { this.prefix = prefix; }
String greet(String name) { return prefix + ", " + name + "!"; }
}
Greeter g = new Greeter("Hello");
java.util.function.Function<String, String> greetFn = g::greet;
System.out.println(greetFn.apply("Alice")); // Hello, Alice!
System.out.println(greetFn.apply("Bob")); // Hello, Bob!Использование как Supplier
Метод экземпляра без аргументов, привязанный к определённому объекту, соответствует Supplier<T>:
StringBuilder sb = new StringBuilder("Hello World");
java.util.function.Supplier<String> toString = sb::toString;
System.out.println(toString.get()); // Hello World
sb.append(" !");
System.out.println(toString.get()); // Hello World ! (sb is live)Использование как Predicate
Методы экземпляра, возвращающие логическое значение, соответствуют Predicate, если они привязаны к определённому экземпляру:
String prefix = "Java";
java.util.function.Predicate<String> startsWith = prefix::equals;
// Hmm, this checks if prefix.equals(candidate).
// More useful:
Predicate<String> startsWithJ = s -> s.startsWith("J");
// But a specific instance Predicate:
StringBuilder pattern = new StringBuilder("hello");
Predicate<String> equalsHello = ((CharSequence)"hello")::equals;
System.out.println(equalsHello.test("hello")); // true
System.out.println(equalsHello.test("world")); // falseШаблон слушателя и обратного вызова
Ссылки на методы конкретного экземпляра идеально подходят для слушателей событий и обратных вызовов: они естественным образом сохраняют объект-обработчик:
class EventHandler {
void onEvent(String event) {
System.out.println("Handling: " + event);
}
}
EventHandler handler = new EventHandler();
List<String> events = List.of("click","hover","submit");
events.forEach(handler::onEvent); // captures the specific handler instanceПрактика: регистратор, привязанный к классу
Привяжите регистратор к определённому экземпляру регистратора, чтобы использовать его в качестве потребителя:
import java.util.logging.*;
Logger log = Logger.getLogger("MyApp");
List<String> messages = List.of("Starting","Processing","Done");
messages.stream()
.map(String::toUpperCase)
.forEach(log::info); // log is the specific Logger instanceСсылка сохраняет состояние на момент привязки
Состояние объекта, доступное через ссылку, отражает его текущее состояние, а не снимок, сделанный при создании ссылки:
List<String> list = new ArrayList<>(List.of("A","B"));
java.util.function.Supplier<Integer> sizeRef = list::size;
System.out.println(sizeRef.get()); // 2
list.add("C");
System.out.println(sizeRef.get()); // 3 (reflects live state)Сравнение конкретного и произвольного экземпляров
Две разные формы ссылки на метод выглядят похоже — разберитесь в различиях:
// Specific instance: s is captured at binding
String s = "hello";
Predicate<String> p1 = s::equalsIgnoreCase; // String::equalsIgnoreCase bound to 'hello'
// Arbitrary instance: receiver is the stream element
Function<String, String> p2 = String::toUpperCase; // receiver IS the elementПрактический пример: потокобезопасное делегирование методов
Привяжите синхронизированный метод объекта службы к функциональному интерфейсу для безопасного асинхронного использования:
class Counter {
private int count = 0;
synchronized void increment(String ignored) { count++; }
int get() { return count; }
}
Counter c = new Counter();
List<String> tasks = List.of("t1","t2","t3");
tasks.forEach(c::increment);
System.out.println(c.get()); // 3Если захваченный экземпляр равен null
Если захваченный объект равен null в момент создания ссылки на метод, NullPointerException возникает во время вызова, а не во время привязки:
StringBuilder sb = null;
// Reference is created without error:
java.util.function.Supplier<String> ref = sb::toString;
try {
ref.get(); // NPE thrown here
} catch (NullPointerException e) {
System.out.println("NPE at invocation");
}Сводка сравнения
Сравнение трёх форм ссылок на методы:
- ClassName::staticMethod — статический метод, без получателя
- instance::instanceMethod — привязан к определённому объекту
- ClassName::instanceMethod — получателем является элемент потока (произвольный экземпляр)
Быстрая проверка
Дано EventHandler h = new EventHandler(); list.forEach(h::handle); — что является получателем вызова handle для каждого элемента?
Итоги: ссылки на методы конкретного экземпляра
Основные выводы:
- Синтаксис: instance::methodName — захватывает определённый объект
- Захваченный объект является получателем каждого вызова
- Идеально подходит для обратных вызовов, слушателей и сценариев журналирования
- Текущее состояние захваченного экземпляра доступно через ссылку
- NPE возникает во время вызова, если экземпляр равен null (не во время привязки)
Часто задаваемые вопросы
Урок «Ссылки на методы экземпляра конкретного объекта» бесплатный?
Да — полный текст урока «Ссылки на методы экземпляра конкретного объекта» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.
Чему я научусь в уроке «Ссылки на методы экземпляра конкретного объекта»?
Сохраняйте ссылку на конкретный объект и используйте один из его методов экземпляра для обратных вызовов и обработчиков. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Java Academy?
Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Ссылки на методы экземпляра конкретного объекта»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Java Academy?
Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Ссылки на статические методы
- Ссылки на методы экземпляра конкретного объекта
- Ссылки на методы произвольного экземпляра
- Ссылки на конструкторы