4

What would be the best practice to declare lambdas in Java8 code? How it was designed to be used?

For example, let's say that we have a method that accept a Function. I want to provide function implementation that can be reusable. So I can do this:

[A] Implement a Function interface:

public class Foo implements Function<A,B> {
    public B apply(A a) {...}
}
...
useFunction(new Foo());

[B] Declare Function as lambda in some static field:

public interface Foo {
    Function<A,B> bar = it -> { ....}
}
...
useFunction(Foo.bar);

[C] Use method reference:

public class Foo {
    public static B bar(A a) {...}
}
...
useFunction(Foo::bar);

Until functional programing in java8, I tried not to pollute code with statics. However, now I am somehow 'forced' to use statics (or global singletons) for storing reusable lambdas.

EDIT

I have code that returns the following on several places:

return CompletableFuture.supplyAsync(() -> {
...
}
.exceptionally(FooExceptionWrapper::wrap);

As you see, I want to share the wrapper (that is a Function) instances, and yet to remain fluent with the code. There are many ways how we can share this.

If I create new instance every time (like in A) then we are going to create new instance on every call, which is fine; yet GC is going to be called more frequently. I can instead create a singleton and since this is a Function, sharing it across the threads is not going to be a problem. So I might store it in some variable. Now, I would like to put the handling code out of this class (simple to reduce the size and the responsibility of the class). So I use approach A - but still want to see if there is more 'proper' way for this. There are not many java8 projects out there, and lot of people simple use static fields (like in B); Im just questioning all that.

6
  • 2
    cross-posted and closed at SO: stackoverflow.com/questions/27693304/… – gnat Dec 30 '14 at 15:37
  • what's wrong with statics? – ratchet freak Dec 30 '14 at 15:42
  • 2
    I am not entirely sure that you understand what lambdas are and how and why to use them. Have you started with something like the Oracle lambda tutorial? – user22815 Dec 30 '14 at 15:45
  • 3
    Answers aren't supposed to correct your question, they're supposed to answer it. In your case you may need to explain your question better or take a step back and ask a more basic question to get yourself directed towards a better question. I'm not sure I understand your question myself... – Jimmy Hoffa Dec 30 '14 at 18:01
  • 1
    Very good observation @JimmyHoffa. I edited the question. – igor Dec 30 '14 at 19:39
5

If you expect a function to be reused or shared, make it a method and use a method reference. If you just need a short, throwaway piece of logic, make it a lambda. Explicitly creating instances of a functional interface has no advantages and has disadvantages:

  • Less idiomatic
  • More boilerplate
  • You commit to types up front, while a method reference or lambda will match any functional interface with the right signature.
  • Most likely less efficient
4
  • When you say: "...make it a method and use a method reference", that means to create a class with static method(s); so we can reuse on several places? – igor Dec 31 '14 at 12:50
  • @igor It doesn't have to be a static method and it doesn't need to have its own class. As with all other things, put it in the smallest scope that makes sense. If it's only going to be used internally in the current class, it makes sense to make it a private method. – Doval Dec 31 '14 at 13:07
  • Sure. Anyway I really want to move the function code into the separate class :) so to reduce the size of the class where function is being used. Thanx. – igor Dec 31 '14 at 13:17
  • I couldn't agree more with @Doval's answer. lambdas [link] cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html are anonymous methods. they are not meant to be re-used. Additionally, they can't be unit tested. I would rephrase the question as "how to expose refer-able methods" – Naveen Jul 10 '17 at 12:27
2

I would generally prefer method A because it is the most familiar idiom to Java programmers (being the only one of your options that was available before Java 8) and because it generates slightly better bytecode than C (which involves an extra automatically generated adapter class) which may result in more efficient code.

I would choose method C if (and only if) some aspect of the problem being solved made it more readable, for instance if you have a large family of related functions to choose from that could sensibly all be implemented in one class.

I would never use option B, which seems to me to be using lambdas for the sake of it.

2

There are actually many more ways to do this in Java 8.

To start, if what you want to do in function is simple enough (e.g. a one liner), than probably a simple lambda is the way to go.

foo( it -> it.getValue() > 10 ? "A" : "B" )

In this approach you probably won't have to worry for how many instances of the lambda target object are created, the JLS makes concessions so that the same instance can be be reused (unless it is a capturing lambda)

Now, if the code is a bit more complex, than you may consider using method references. There are many types of method references, not just the static method reference that you mention in your example.

You may want to read State of Lambda to make that clearer.

Certainly the definition of a static field in an interface to contain the lambda target object sounds like a pretty bad idea to me too. Static fields in interfaces are typically used for constants since they are by default static and final, and therefore I have difficulty conceiving a good scenario for this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.