Java Lambdas : How it works in JVM & is it OOP?

Lambda expressions don't get translated into anonymous inner classes, they use invoke dynamic that was introduced in Java 7 to execute functional methods. Check this out.

Do they violate OOP? I don't think that you should care. Lambdas make your code less verbose, easier to understand, and "easier" to parallelise. And thats what you should care about.

From Brain Goetz comment:

We don't get paid to write object-oriented programs or functional programs, we get paid to write working programs.


  • Lambda expression is compiled using invokedynamic bytecode.
  • Lambda implementation is stored in the same class file as a special private method.
  • Whether an object is created to invoke lambda depends on the situation. In the trivial cases lambda gets translated to a constant method handle.
  • To instantiate a lambda HotSpot creates an anonymous class that implements lambda's functional interface. This class does not belong to any ClassLoader.

See more details from the specification lead of Lambda Expressions JSR.


I wouldn't waste my time thinking whether the lambda expressions are a violation of OO principles. Its goal is to increase the power of a language and not to write an OO code, I don't see how lambdas can violate encapsulation, inheritance or polymorphism.

This article explains how Java handles lambda expressions:

What’s interesting about Lambda expressions is that from the JVM’s perspective they’re completely invisible. It has no notion of what an anonymous function or a Lambda expression is. It only knows bytecode which is a strict OO specification. It’s up to the makers of the language and its compiler to work within these constraints to create newer, more advanced language elements.

Considering the following code:

List names = Arrays.asList("1", "2", "3");
Stream lengths = names.stream().map(name -> name.length());

... It begins quite simply by loading the names var and invokes its .stream() method, but then it does something quite elegant. Instead of creating a new object that will wrap the Lambda function, it uses the new invokeDynamic instruction which was added in Java 7 to dynamically link this call site to the actual Lambda function.

aload_1 //load the names var

// call its stream() func
invokeinterface java/util/List.stream:()Ljava/util/stream/Stream;

//invokeDynamic magic!
invokedynamic #0:apply:()Ljava/util/function/Function;

//call the map() func
invokeinterface java/util/stream/Stream.map:
(Ljava/util/function/Function;)Ljava/util/stream/Stream;

InvokeDynamic is an instruction that was added in Java 7 to make the JVM less strict, and allows dynamic languages to bind symbols at run-time, vs. doing all the linkage statically when the code is compiled by the JVM.

The Lambda code

aload_0
invokevirtual java/lang/String.length:()
invokestatic java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
areturn