Интерфейс JDK для обработки универсального параметра - PullRequest
14 голосов
/ 13 декабря 2011

Есть ли интерфейс от JDK, который выглядит примерно так:

public interface Callback<T> {
    public void process(T t);
}

Требуется реализовать обратный вызов, который запускает код, но ничего не возвращает.

Я мог бы написать свой собственный (просто используя здесь пример кода), но я бы хотел использовать существующее колесо, если оно существует, а не изобретать его заново.

Ответы [ 9 ]

10 голосов
/ 13 декабря 2011

Так что вам нужно что-то вроде

interface Foo<T>
    bar(T)

Только 3 интерфейса в JDK такие же

java.nio.file.DirectoryStream$Filter<T>

    boolean accept(T entry) throws IOException;


java.lang.Comparable<T>

    int compareTo(T o);


javax.xml.ws.Provider<T>

    T invoke(T request);

Очевидно, они тебе не понравятся.

Async IO имеет интерфейс обратного вызова, но он немного сложнее:

java.nio.channels.CompletionHandler<V,A>

    void completed(V result, A attachment);

    void failed(Throwable exc, A attachment);
4 голосов
/ 13 декабря 2011

Нет, я не верю, что сейчас есть такой интерфейс.В настоящее время планируется, что в JDK 8 будет такой интерфейс, называемый Block (с использованием метода apply, я думаю) ... хотя имя вполне может измениться между сейчас и потом.

3 голосов
/ 18 декабря 2011

Это похоже на Function в Guava, за исключением того, что функция может возвращать что-то. Таким образом, это выглядит как

public interface Callback<T> extends Function<T, Void> {
}

Не является частью JDK, но Гуава теперь так широко используется, что вам может пригодиться.

2 голосов
/ 20 декабря 2011

По моему опыту, в JDK нет такого легкодоступного интерфейса. Дженерики только пришли поздно в игру Java. До этого была необходимость передавать несколько типизированных аргументов обратному вызову в полутиповом безопасном виде и без предварительного знания структуры этих аргументов (я говорю «полупериодный безопасный», потому что слушатели событий были изобретены для проверки типа события). и снимали по мере необходимости). Вы не могли бы построить этот механизм без обобщений, и они никогда не перепроектировали весь JDK, чтобы иметь в виду обобщения (за исключением API коллекций и некоторых других). Это было бы грандиозным предприятием с небольшими выгодами (в конце концов, все работало , как ожидалось).

Следовательно, шаблон наблюдателя / слушателя, который распространен в библиотеках JDK (см. java.util.EventObject, java.util.EventListerner и их использование). Java также считает, что при определении интерфейса EventListener он должен быть немного более подробным. Для более ясных реализаций специализированные реализации этого шаблона должны заставить имя метода обратного вызова демонстрировать назначение кода (которое обычно также совпадает с именем события). Например, ActionEvent#actionPerformed(ActionEvent e).

Другой возможной причиной отсутствия этого интерфейса является то, что он не используется в самом JDK. Иногда вы хотите, чтобы Callback<T> другие для Callback<T, V> или даже Callback<T, R, V> и т. Д. Предоставление этих интерфейсов без какого-либо реального варианта использования (внутри JDK) на самом деле не очень политика проектирования. Отсутствие поддержки для таких полезных конструкций является основной причиной существования Guava и Apache Commons (среди прочих).

В любом случае, я согласен с @JB Nizet, что вы должны использовать Guava. Мы не указали, почему и как вы используете интерфейс, так что это оставляет много места для спекуляций, но по любой причине у Guava, вероятно, будут другие функции, которые могут пригодиться.

2 голосов
/ 13 декабря 2011

Реальный вопрос здесь, почему? Почему вы считаете, что определение вашего интерфейса для этого хуже, чем использование Java? Что ты собираешься получить? Вы потеряете возможность выбрать подходящее имя. Я думаю, что это об этом. Если бы у вас была причина использовать существующий интерфейс, предоставляемый библиотеками Java, вы бы уже знали его имя, потому что знали бы, с какой частью библиотеки вы планируете взаимодействовать. Создание интерфейса одним методом не изобретает колесо.

1 голос
/ 16 августа 2014

В Java 8 класс java.util.function.Consumer делает именно то, что вы хотите.

У него есть один метод не по умолчанию, который принимает универсальный тип и ничего не возвращает:

public interface Consumer<T> {

    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        // ...
    }
}        
1 голос
/ 21 декабря 2011

Я использовал Callable (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html) для реализации обратных вызовов / функторов в Java.

interface Callable<V> {
    public V call();
}

Вы можете обработать это, используя материал Executors в java.util.concurrent.

1 голос
/ 21 декабря 2011

Если вы хотите применить шаблон проектирования Observer, Java поддерживает его в своей стандартной библиотеке начиная с JDK 1.0. Интерфейс, который вы ищете, это java.util.Observer. Другая сторона шаблона - это класс java.util.Observable. По сути, вы расширяете java.util.Observable, а затем регистрируете своих наблюдателей (насколько я понимаю, наблюдатель может наблюдать более одного наблюдаемого одновременно). Это довольно древние вещи, так что будьте осторожны: нет дженериков.

0 голосов
/ 13 декабря 2011

Это называется обработкой аннотации. JSR 269: подключаемый API обработки аннотаций определяет API и является частью JDK 6. Вы можете начать с здесь и здесь .

...