Как использовать ссылку на метод в качестве будущего обратного вызова? - PullRequest
0 голосов
/ 17 января 2019

Когда я пытаюсь использовать что-то вроде этого

class Example {
    ...

    private Future<String> asyncMethod() {
        ...
        return somePromise;
    }

    private static void callback(Future<String> future) {
        System.out.println(future.getNow());
    }

    public static void main(String[] args) {
        asyncMethod().addListener(Example::callback);
    }
}

Я получаю ошибку

Example.java:[17,34] incompatible types: invalid method reference
   incompatible types: io.netty.util.concurrent.Future<capture#1 of ? super java.lang.String>
   cannot be converted to io.netty.util.concurrent.Future<java.lang.String>

Нет ошибок с анонимным классом в качестве слушателя

asyncMethod().addListener(new GenericFutureListener<Future<String>>() {
    @Override
    public void operationComplete(Future<String> future) throws Exception {
        System.out.println(future.getNow());
    }
});

Но это уродливо и многословно :( Что я могу сделать, чтобы решить эту проблему самым элегантным способом?

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Вы можете привести ссылку на метод

asyncMethod().addListener((GenericFutureListener<Future<String>>) Example::callback);

Это менее многословно, но все же не идеально. Чтобы немного улучшить это решение, вы можете переместить определение длинного типа в функциональный интерфейс

class Example {
    @FunctionalInterface
    private interface Callback extends GenericFutureListener<Future<String>> {
        void operationComplete(Future<String> future) throws Exception;
    }

    private static void callback(Future<String> future) {
        System.out.println(future.getNow());
    }

    public static void main(String[] args) {
        asyncMethod().addListener((Callback) Example::callback);
    }
}

Или вы можете заключить обратный вызов в лямбда с набранным аргументом

asyncMethod().addListener((Future<String> f) -> callback(f));

Может быть, это можно сделать лучше, ИДК.

0 голосов
/ 17 января 2019

Доступны следующие варианты:

  1. используйте лямбду (короче, чем полный анонимный класс, но все же не оптимально):

asyncMethod().addListener((GenericFutureListener<Future<String>>) future -> Application.callback(future))

  1. Исправить параметр вашего обратного вызова в:

private static void callback(Future<? super String> future) {

из простого Future<String> future, таким образом, вы также можете использовать обратный вызов.

Примечание. Если вы запутались в проблеме ? extends vs ? super генериков, у меня этот пост добавлен в закладки по той же причине.

...