I am new to Lambda Expressions in Java so please don't react too harsh if this question appears silly: What is the actual object that gets implemented if I assign it to a FunctionalInterface
? I.e., if I do List<String> lst = new ArrayList<>()
I implement an ArrayList
object. What is the object that gets created if I do Function<String,String> fct = s -> s
? And is that object immutable, i.e. does it make sense to have a public static final Function<String,String> REUSE_OFTEN = s -> String.valueOf(s)
?

- 1,302
- 2
- 11
- 31
-
1You could print out `REUSE_OFTEN.getClass()` and see what its class type is. My guess is it's something synthesized by the compiler and not part of the API. – markspace Jan 12 '18 at 21:43
-
Also, as a general rule of thumb, it's important to note that the keyword `final` doesn’t really achieve immutability for reference types. all it does is stop the field it qualifies from being updated; – Ousmane D. Jan 12 '18 at 21:54
2 Answers
When you write a lambda expression -
Function<String,String> fct = s -> s;
It simply creates an anonymous class that implements Function<String, String>
interface and overrides its only method apply()
with the implementation you have provided by s -> s
. And assign this object to Function<String, String>
reference.
Function<String,String> fct = new Function<>() {
@Override
public String apply(String s) {
return s;
}
};
And it is an immutable object and it does make sense to have a public static final Function<String,String> REUSE_OFTEN = s -> String.valueOf(s)
as you can reuse same object to apply this operation with the different input.

- 517
- 5
- 16
-
Initially, the lambda's body will be desugaed into a static method. After that, at run-time, the wrapper class will be generated for this method. In terms of JVM it's not an anonymous class... – Alex Jan 12 '18 at 22:43
-
1
I.e., if I do List lst = new ArrayList<>() I implement an ArrayList object.
You instantiate a ArrayList
rather.
What is the object that gets created if I do Function fct = s -> s? And is that object immutable, i.e. does it make sense to have a public static final Function REUSE_OFTEN = s -> String.valueOf(s)?
Lambdas are not the same thing than anonymous classes in terms of byte codeand also in terms of behavior/functioning. This last one is close enough but not exactly the same.
Here are two methods that do the same thing, one with lambda the other with anonymous class :
public class CompareBoth {
public void lambda() {
Function<String,String> fct = s -> s;
fct.apply("a");
}
public void anonymousClass() {
Function<String,String> fct = new Function<String, String>() {
@Override
public String apply(String t) {
return t;
}
};
fct.apply("a");
}
}
Here the disassembled code :
public class cli.CompareBoth {
public cli.CompareBoth();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void lambda();
Code:
0: invokedynamic #2, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;
5: astore_1
6: aload_1
7: ldc #3 // String a
9: invokeinterface #4, 2 // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
14: pop
15: return
public void anonymousClass();
Code:
0: new #5 // class cli/CompareBoth$1
3: dup
4: aload_0
5: invokespecial #6 // Method cli/CompareBoth$1."<init>":(Lcli/CompareBoth;)V
8: astore_1
9: aload_1
10: ldc #3 // String a
12: invokeinterface #4, 2 // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
17: pop
18: return
}
We can see that the JVM treat them differently.
What is the actual object that gets implemented ?
As a lambda is created this JVM instruction is performed :
0: invokedynamic #2, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;
InvokeDynamic
that was introduced in Java 7 is specified as a bytecode instruction that facilitates the implementation of dynamic languages (for the JVM) through dynamic method invocation.
You can read this javaworld page to have more information.
Now, does it really matter as you develop ?
In most of cases, it doesn't.
Functional interfaces are functionnaly close to anonymous interfaces with multiple slight differences.
Conceptually, I think that it is acceptable to consider them in this way.
About functional interface immutability :
Functional interfaces may have a state but are designed to be immutable.
So you can reuse them if it makes sense.
But InvokeDynamic
may be optimized by JVM.
So you should not reuse them in your code just to spare some objects.
Instead of, extract the functional interface in a constant or a variable because it makes things more clear or it avoids duplication.

- 125,838
- 23
- 214
- 215
-
Should we say that lambdas capturing local variables are also stateless? – tsolakp Jan 12 '18 at 23:14
-
-
-