Lambdas vs Anonymous Classes

So far in java we have seen interfaces and abstract classes, with a single abstract method, being used as function types. Their instances, known as function objects, represent functions or actions. Since JDK 1.1, the primary means of creating a function object was the anonymous class.

Below is a code snippet to sort a list of strings in order of length, using an anonymous class to create the sort’s comparison function.

Collections.sort(words, new Comparator() {
     public int compare(String s1, String s2) {
        return Integer.compare(s1.length(), s2.length());
     }
});

So there we have one anonymous class which is implementing Comparator interface and implementing its compare(…) method.

By Java 8, the language formalized the notion that interfaces with a single abstract method are special and deserve special treatment. These interfaces are now known as functional interfaces and the java allows you to create instances of these interfaces using lambda expressions or lambdas for short. Lambdas are similar in function to anonymous classes.

Lets re-write the above code with lambda expression.

Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length());

Note that the types of the lambda (Comparator), its parameters (s1 and s2, both String) and its return value (int) are not present in the code.  The compiler itself drew to a logical conclusion of these types from context, using a process known as type inference. In short, type inference, can be described as “Omit the types of all lambda parameters unless their presence makes your program clearer.” If the compiler generates an error telling you it can’t infer the type of a lambda parameter, then specify it. Sometimes you may have to cast the return value or the entire lambda expression, but this is rare.

There are some limitations with Lambdas as well.

Unlike methods and classes, lambdas lack names and documentation; if a computation isn’t self-explanatory, or exceeds a few lines, don’t put it in a lambda. One line is ideal for a lambda, and three lines is a reasonable maximum. If you violate this rule, it can cause serious harm to the readability of your programs. If a lambda is long or difficult to read, either find a way to simplify it or refactor your program to eliminate it. 

You can think that anonymous classes are obsolete in the era of lambdas. This is almost true but there are a few things you can do with anonymous classes that you can’t do with lambdas. 

  • Lambdas are limited to functional interfaces. If you want to create an instance of an abstract class, you can do it with an anonymous class, but not a lambda,
  • Similarly, you can use anonymous classes to create instances of interfaces with multiple abstract methods,
  • A lambda cannot obtain a reference to itself. In a lambda, the this keyword refers to the enclosing instance, which is typically what you want. In an anonymous class, the this keyword refers to the anonymous class instance.

What is common between lambdas and anonymous classes is that they can not be serialize or deserialize. Therefore, you should rarely serialize a lambda or an anonymous class instance.

As of Java 8, Lambdas as the good candidate to replace anonymous classes. There is no need to use anonymous classes for function objects if we have create instances of types that are not functional interfaces. Lambdas can be used as functional programming technique that was not practical in java with or without anonymous classes previously.

Hope this had cleared your doubts about lambdas vs anonymous classes.