Refactoring anonymous classes (that implement a single method) to lambda expressions, makes your code more succint and readable. For example, here's an anonymous class for a Runnable
and its lambda equivalent:
// using an anonymous class Runnable r = new Runnable() { @Override public void run() { System.out.println("Hello"); } }; // using a lambda expression Runnable r2 = () -> System.out.println("Hello");
However, it's not always that simple!
Here are a couple of gotchas:
1. Different scoping rules
There are different scoping rules between anonymous classes and lambda expressions. For example, in lambda expressions, this
and super
are lexically scoped, meaning they are relative to the enclosing class, but in an anonymous class, they are relative to the anonymous class itself. Similarly, local variables declared in lambda expressions will conflict with variables declared in the enclosing class, but in anonymous classes, they are allowed to shadow variables in the enclosing class. Here is an example:
int foo = 1; Runnable r = new Runnable() { @Override public void run() { // this is ok! int foo = 2; } }; Runnable r2 = () -> { // compile error: Lambda expression's local variable foo cannot // redeclare another local variable defined in an enclosing scope. int foo = 2; };
2. Overloaded methods
If you have an overloaded method, using lambda expressions can result in an ambiguous method call and will require explicit casting. Here is an example:
// Functional interface interface Task { public void execute(); } // Overloaded methods public static void go(final Runnable r) { r.run(); } public static void go(final Task t) { t.execute(); } // Calling the overloaded method: // When using an anonymous class, there is no ambiguity because // the type of the class is explicit at instantiation go(new Task() { @Override public void execute() { System.out.println("Hello"); } }); // When using a lambda expression, there is a compile error! // The method go(Runnable) is ambiguous go(() -> { System.out.println("Hello"); }); // This ambiguity can be solved with an explicit cast go((Task)() -> { System.out.println("Hello"); });
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.