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