Как написать лямбда-выражение для абстрактного класса

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

public abstract class SessionExecutionBody {
   public Object execute() {
     executeWithoutResult();
     return null;
   }

   public void executeWithoutResult() {}
} 

и я реализую класс следующим образом:

final HTTPDestination destination = sessionService.executeInLocalView(new SessionExecutionBody() {
            @Override
            public Object execute() {
                userService.setCurrentUser(userService.getAdminUser());
                final String destinationName = getConfigurationService().getConfiguration().getString(DESTINATION_PROPERTY);
                return getHttpDestinationService().getHTTPDestination(destinationName);

Когда я запускаю sonarLint, это показывает серьезную проблему, преобразует этот анонимный класс в лямбда-выражение, но я не могу найти способ исправить то же самое. Могу ли я преобразовать это выражение в лямбду?

2 ответа

Решение

Боюсь, ты не сможешь. Это не функциональный интерфейс с одним абстрактным методом для его реализации в стиле лямбда.

Могу ли я преобразовать это выражение в лямбду?

Вы можете сделать следующие изменения:

@FunctionalInterface // to guarantee the next rule
interface SessionExecutionBody {
    Object execute(); // has exactly one abstract method

    default void executeWithoutResult() {} // other methods should be default/static
}
...
sessionService.executeInLocalView(() -> { /* a body */ return ...; })

Вы не можете конвертировать подкласс abstract class в лямбда-выражение и инструмент аудита, говорящий иначе, может считаться ошибкой. Как показал Эндрю Тобилко, одним из решений использования здесь лямбда-выражения будет преобразование abstract class в interface,

Если это не вариант, например, из-за совместимости с другим кодом, использующим этот класс, вы можете предложить фабричные методы для реализаций, достаточно простых, чтобы извлечь выгоду из лямбда-выражений, в то же время позволяя создавать подклассы:

public abstract class SessionExecutionBody {

    public static SessionExecutionBody withResult(Supplier<?> s) {
        Objects.requireNonNull(s);
        return new SessionExecutionBody() {
            @Override public Object execute() { return s.get(); }
        };
    }
    public static SessionExecutionBody withoutResult(Runnable r) {
        Objects.requireNonNull(r);
        return new SessionExecutionBody() {
            @Override public void executeWithoutResult() { r.run(); }
        };
    }

    public Object execute() {
        executeWithoutResult();
        return null;
    }

   public void executeWithoutResult() {}
}

который вы можете использовать как

final HTTPDestination destination = sessionService.executeInLocalView(
    SessionExecutionBody.withResult(() -> {
        userService.setCurrentUser(userService.getAdminUser());
        final String destinationName = 
            getConfigurationService().getConfiguration().getString(DESTINATION_PROPERTY);
        return getHttpDestinationService().getHTTPDestination(destinationName);
    }));
Другие вопросы по тегам