47. Lambdas vs Anonymous Classes
Lambdas are concise functional interface implementations; they cannot capture mutable local variables (only effectively-final), have no this reference of their own, and should never be serialized.
Explanation
Lambdas replace single-method anonymous classes with terser syntax. Key differences: a lambda has no this โ inside a lambda, this refers to the enclosing class instance, not the lambda itself. An anonymous class creates its own this.
Effectively final capture: a lambda can capture local variables from the enclosing scope only if those variables are final or effectively final (never reassigned after initialisation). Capturing a mutable variable is a compile error. Captured object references can still have their object mutated โ just the reference itself must be stable.
Do not serialise lambdas: lambda serialisation is technically possible (if the target interface extends Serializable) but the serialised form is implementation-specific and brittle across JVM versions.
Example
import java.util.List;
import java.util.function.Predicate;
public class LambdasVsAnonymous {
interface Greeter { String greet(String name); }
String instanceField = "Hello";
void demo() {
String localVar = "World"; // effectively final
// Anonymous class: has its own 'this', verbose
Greeter anon = new Greeter() {
@Override public String greet(String name) {
// 'this' here refers to the anonymous class instance
return instanceField + " from anon, " + name;
}
};
// Lambda: concise, 'this' is the outer LambdasVsAnonymous instance
Greeter lambda = name -> instanceField + " lambda, " + name; // captures 'this' implicitly
System.out.println(anon.greet("Alice")); // Hello from anon, Alice
System.out.println(lambda.greet("Bob")); // Hello lambda, Bob
// Effectively final โ OK
// localVar = "changed"; // uncommenting this causes compile error in lambda below
Predicate<String> check = s -> s.equals(localVar); // captures effectively-final localVar
System.out.println(check.test("World")); // true
// Mutable state via array trick (workaround, rarely needed โ prefer streams)
int[] count = {0};
List.of("a", "b", "c").forEach(s -> count[0]++); // array ref is final, content isn't
System.out.println("Count: " + count[0]); // 3
}
public static void main(String[] args) {
new LambdasVsAnonymous().demo();
}
}Sources
- https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html โ Lambda expressions
- https://openjdk.org/jeps/126 โ JEP 126: Lambda Expressions