Devendra
Devendra

Reputation: 1884

how to write lambda expression for the abstract class

I have abstract class which have two methods as follows:

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

   public void executeWithoutResult() {}
} 

and I implement the class as follows:

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);

When I run sonarLint its showing major issue convert this anonymous class to lambda expression but I am unable to find the way to right the same , Can I convert that expression into a lambda?

Upvotes: 5

Views: 4536

Answers (2)

Holger
Holger

Reputation: 298529

You can’t convert the subclass of an abstract class into a lambda expression and an audit tool saying otherwise can be considered to have a bug. As Andrew Tobilko showed, one solution to use a lambda expression here, would be converting the abstract class into an interface.

If that’s not an option, e.g. due to compatibility with other code using that class, you may offer factory methods for implementations simple enough to benefit from lambda expressions, while still allowing subclassing:

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() {}
}

which you can use as

final HTTPDestination destination = sessionService.executeInLocalView(
    SessionExecutionBody.withResult(() -> {
        userService.setCurrentUser(userService.getAdminUser());
        final String destinationName = 
            getConfigurationService().getConfiguration().getString(DESTINATION_PROPERTY);
        return getHttpDestinationService().getHTTPDestination(destinationName);
    }));

Upvotes: 3

Andrew
Andrew

Reputation: 49656

I'm afraid you can't. That is not a functional interface with one abstract method to implement it in the lambda style.

Can I convert that expression into a lambda?

You could if you make the following changes:

@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 ...; })

Upvotes: 8

Related Questions