Как написать лямбда-выражение для абстрактного класса
У меня есть абстрактный класс, который имеет два метода следующим образом:
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);
}));