Inner lambda reference Outer lambda variable - java

There is a Outer lambda that contains inner lambda whis tries to reference var in Outer lambda, how does it possible?
Im try to understand what this expression will look like when its compiled to make this possible.
public static void main(String[] args) {
ExecutorService service = Executors.newScheduledThreadPool(10);
DoubleStream.of(3.14159, 2.71828)
.forEach(c -> service.submit(
() -> System.out.println(c)));
I'm guess is will compiled to something like this:
new Consumer<Double>() {
#Override
public void accept(Double aDouble) {
new Runnable() {
#Override
public void run() {
System.out.println(aDouble);
}
};
}
};
Am i right?

The compiled code is closer to
class MyClass {
public static void main(String[] args) {
ExecutorService service = Executors.newScheduledThreadPool(10);
DoubleStream.of(3.14159, 2.71828)
.forEach(new DoubleConsumer() {
#Override public void accept(double value) {
lambda1(service, value);
}
});
}
private static void lambda1(ExecutorService service, double c) {
service.submit(new Runnable() {
#Override public void run() {
lambda2(c);
}
});
}
private static void lambda2(double c) {
System.out.println(c);
}
}
not having any nesting anymore. Actually, the compiled code doesn’t contain anonymous inner classes. There will be generate classes at runtime fulfilling the interfaces DoubleConsumer and Runnable though, which will invoke these synthetic methods holding the bodies of your lambda expression.
But this sketch is already sufficient to demonstrate that there is no real technical difference between “outer lambda” and “inner lambda”. The nesting exists on the source code level, allowing you to express your intent concisely.
See also “How will Java lambda functions be compiled?”

The innermost lambda can access c from its enclosing lambda because c is effectively final, because nothing ever assigns to it. From the linked portion of the spec:
A method, constructor, lambda, or exception parameter (§8.4.1, §8.8.1, §9.4, §15.27.1, §14.20) is treated, for the purpose of determining whether it is effectively final, as a local variable whose declarator has an initializer.
and then above that
A local variable whose declarator has an initializer (§14.4.2) is effectively final if all of the following are true:
It is not declared final.
It never occurs as the left hand side in an assignment expression (§15.26). (Note that the local variable declarator containing the initializer is not an assignment expression.)
It never occurs as the operand of a prefix or postfix increment or decrement operator (§15.14, §15.15).
So even though c isn't explicitly final, it's effectively final.
I'm guess is will compiled to something like this:
...
Am i right?
I think that's about it in effect; the compiler doesn't actually do that, lambdas are their own thing. If we wanted to underscore the fact that c is effectively final, we might add final to its parameter declaration there.

Related

Value of "this" in an anonymous class vs a lambda expression

I am little bit confused with the different behavior of an anonymous class and a lambda expression.
When I'm using a lambda expression:
//Test.java
Runnable r1 = () -> System.out.println(this);
Runnable r2 = () -> System.out.println(toString());
#Override
public String toString() {
return "Hello World!";
}
// in main method
new Test().r1.run();
new Test().r2.run();
Output : Hello World!
Hello World!
When using an anonymous class:
Runnable r1 = new Runnable() {
#Override
public void run() {
System.out.println(this);
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
System.out.println(toString());
}
};
#Override
public String toString() {
return "Hello World!";
}
// in main method
new Test().r1.run();
new Test().r2.run();
Output : Package_Name.Test$1#1db9742
Package_Name.Test$2#106d69c
Can someone please explain the different behavior?
In a lambda expression, this is lexically bound to the surrounding class, while in the anonymous class this is lexically bound to the anonymous class.
The Java Language Specification describes this behavior at 15.27.2:
Unlike code appearing in anonymous class declarations, the meaning of names and the this and super keywords appearing in a lambda body, along with the accessibility of referenced declarations, are the same as in the surrounding context (except that lambda parameters introduce new names).
The transparency of this (both explicit and implicit) in the body of a lambda expression - that is, treating it the same as in the surrounding context - allows more flexibility for implementations, and prevents the meaning of unqualified names in the body from being dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to talk about itself (either to call itself recursively or to invoke its other methods), while it is more common to want to use names to refer to things in the enclosing class that would otherwise be shadowed (this, toString()). If it is necessary for a lambda expression to refer to itself (as if via this), a method reference or an anonymous inner class should be used instead.
In order to reference this of the surrounding class from inside an anonymous class, you will have to use a qualified this.
Runnable r1 = new Runnable() {
#Override
public void run() {
System.out.println(Test.this); // or Test.this.toString()
}
};

Java 8 Lambda Can't Call Default Interface Methods [duplicate]

I have created a simple interface using java8. In that it contains one method and one default method.
interface Lambda{
default void dummy(){
System.out.println("Call this..");
}
void yummy();
}
I'm trying to us these two methods using the historical way like
public class DefaultCheck {
public static void main(String[] args) {
DefaultCheck check = new DefaultCheck();
check.activate(new Lambda() {
#Override
public void yummy() {
dummy();
}
});
}
void activate(Lambda lambda){
lambda.yummy();
}
}
Now i'm trying to implement the same thing using lambda expression, getting error like `dummy is undefined`
check.activate(() -> {
dummy();
});
Can any one please suggest, how to implement this scenario using Lambda expression ??
It can't be done.
JLS 15.27.2 addresses this:
Unlike code appearing in anonymous class declarations, the meaning of
names and the this and super keywords appearing in a lambda body,
along with the accessibility of referenced declarations, are the same
as in the surrounding context (except that lambda parameters introduce
new names).
The transparency of this (both explicit and implicit) in the body of a
lambda expression - that is, treating it the same as in the
surrounding context - allows more flexibility for implementations, and
prevents the meaning of unqualified names in the body from being
dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to
talk about itself (either to call itself recursively or to invoke its
other methods), while it is more common to want to use names to refer
to things in the enclosing class that would otherwise be shadowed
(this, toString()). If it is necessary for a lambda expression to
refer to itself (as if via this), a method reference or an anonymous
inner class should be used instead.
The inner class implementation works since the code is called as if you coded:
check.activate(new Lambda() {
#Override
public void yummy() {
this.dummy();
}
});
Our problem now is that lambdas do not introduce a new scope. So, if you want your lambda to be able to reference itself, you may refine your #FunctionalInterface so that its functional method accepts itself and its required parameters:
check.activate(this_ -> this_.dummy());
where Lambda is defined as:
#FunctionalInterface
public interface Lambda {
void yummy(Lambda this_);
default void yummy() {
yummy(this);
}
default void dummy(){
System.out.println("Call this..");
}
}
If I understand it correctly. You are trying to call a default method in an interface through lambda implementation. I think it can be done.
#FunctionalInterface
interface Value
{
String init(Value a);
default String add(String b)
{
return "added content "+b;
}
default String getResult()
{
String c = init(this);
return c;
}
}
public class Main
{
public static void main(String[] args)
{
Value v = a -> a.add("inpout"); // here I am calling add method in Value interface.
String c = v.getResult();
System.out.println(c);
}
}

Can a lambda access members of its target functional interface?

I have created a simple interface using java8. In that it contains one method and one default method.
interface Lambda{
default void dummy(){
System.out.println("Call this..");
}
void yummy();
}
I'm trying to us these two methods using the historical way like
public class DefaultCheck {
public static void main(String[] args) {
DefaultCheck check = new DefaultCheck();
check.activate(new Lambda() {
#Override
public void yummy() {
dummy();
}
});
}
void activate(Lambda lambda){
lambda.yummy();
}
}
Now i'm trying to implement the same thing using lambda expression, getting error like `dummy is undefined`
check.activate(() -> {
dummy();
});
Can any one please suggest, how to implement this scenario using Lambda expression ??
It can't be done.
JLS 15.27.2 addresses this:
Unlike code appearing in anonymous class declarations, the meaning of
names and the this and super keywords appearing in a lambda body,
along with the accessibility of referenced declarations, are the same
as in the surrounding context (except that lambda parameters introduce
new names).
The transparency of this (both explicit and implicit) in the body of a
lambda expression - that is, treating it the same as in the
surrounding context - allows more flexibility for implementations, and
prevents the meaning of unqualified names in the body from being
dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to
talk about itself (either to call itself recursively or to invoke its
other methods), while it is more common to want to use names to refer
to things in the enclosing class that would otherwise be shadowed
(this, toString()). If it is necessary for a lambda expression to
refer to itself (as if via this), a method reference or an anonymous
inner class should be used instead.
The inner class implementation works since the code is called as if you coded:
check.activate(new Lambda() {
#Override
public void yummy() {
this.dummy();
}
});
Our problem now is that lambdas do not introduce a new scope. So, if you want your lambda to be able to reference itself, you may refine your #FunctionalInterface so that its functional method accepts itself and its required parameters:
check.activate(this_ -> this_.dummy());
where Lambda is defined as:
#FunctionalInterface
public interface Lambda {
void yummy(Lambda this_);
default void yummy() {
yummy(this);
}
default void dummy(){
System.out.println("Call this..");
}
}
If I understand it correctly. You are trying to call a default method in an interface through lambda implementation. I think it can be done.
#FunctionalInterface
interface Value
{
String init(Value a);
default String add(String b)
{
return "added content "+b;
}
default String getResult()
{
String c = init(this);
return c;
}
}
public class Main
{
public static void main(String[] args)
{
Value v = a -> a.add("inpout"); // here I am calling add method in Value interface.
String c = v.getResult();
System.out.println(c);
}
}

What is the breakdown for Java's lambda syntax?

Please explain the syntax for Java 8's lambda methods.
There are a lot of explanations out there for what lambda functions are, but I can't find a thorough explanation of the syntax, and I am finding it very difficult to learn to replicate the syntax correctly because I don't understand why they're written as they are.
Here's a common case that I run into, courtesy NetBeans:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new MainAppJFrame();
});
}
So somehow, the following lambda expression is resolving into an anonymous Runnable object's run() method:
() -> {
// do stuff
}
The -> is the lambda syntax proper, right? And the curly braces are simply containing the anonymous method code. Are the parentheses an empty argument, because in this case we're creating a Runnable.run() method?
This is all rather unclear to me. I assume the compiler knows to instantiate an anonymous Runnable based on the type expected by the SwingUtilities.invokeLater(Runnable) method? What would happen if there were two SwingUtilities.invokeLater methods which differ only in parameter list? Obviously there aren't in this specific case, but it's possible elsewhere:
interface ExampleLambdaConsumer {
public void doSomething(Runnable r);
public void doSomething(java.lang.reflect.Method m);
}
class C implements ExampleLambdaConsumer {
// implementations for doSomething methods here
public static void main(String[] args) {
doSomething(() -> {
// lambda method body here
}
}
}
Syntax is:
arguments -> body
where arguments can be either
()
a single variable if the type of that variable can be inferred from the context
a sequence of variables, with or without types (or since Java 11, with var), in parentheses.
Examples: (x), (x, y), (int x, int y), (var x, var y) (Java 11+).
The following are invalid: (int x, y), (x, var y), (var x, int y)
and body can be either an expression or a {...} block with statements. The expression (other than a method or constructor call) is simply returned, i.e. () -> 2 is equivalent to () -> {return 2;}
In case of lambda expressions like () -> f() (the body is a method or constructor call expression):
if f() returns void, they are equivalent to () -> { f(); }
otherwise, they are equivalent to either () -> { f(); } or () -> { return f(); }). The compiler infers it from the calling context, but usually it will prefer the latter.
Therefore, if you have two methods: void handle(Supplier<T>) and void handle(Runnable), then:
handle(() -> { return f(); }) and handle(() -> x) will call the first one,
handle(() -> { f(); } will call the second one, and
handle(() -> f()):
if f() returns void or a type that is not convertible to T, then it will call the second one
if f() returns a type that is convertible to T, then it will call the first one
The compiler tries to match the type of the lambda to the context. I don't know the exact rules, but the answer to:
What would happen if there were two SwingUtilities.invokeLater methods which differ only in parameter list?
is: it depends on what would be those parameter lists. If the other invokeLater had also exactly one parameter and that parameter would be of type that is also an interface with one method of type void*(), well, then it would complain that it cannot figure out which method you mean.
Why are they written as they are? Well, I think it's because syntax in C# and Scala is almost the same (they use => rather than ->).
The syntax is
(parameter_list_here) -> { stuff_to_do; }
The curly braces can be omitted if it's a single expression. The regular parentheses around the parameter list can be omitted if it's a single parameter.
The syntax only works for all functional interfaces. The #FunctionalInterface annotation tells the compiler that you intend to write such an interface and gives a compile error if you do not meet the requirement(s) - for example it must only have 1 overrideable method.
#FunctionalInterface
interface TestInterface {
void dostuff();
}
Runnable is also declared like that. Other interfaces are not, and they cannot be used with lambda functions.
Now that we've made a new functional interface with a method that takes no parameters, how about we test the question you had about "collision" in the signatures?
public class Main {
private void test(Runnable r) {
}
private void test(TestInterface ti) {
}
public static void main(String[] args) {
test(() -> { System.out.println("test");})
}
#FunctionalInterface
interface TestInterface {
void dostuff();
}
}
Result: compile error: ambigouous call to method test.
You see, the compiler/VM(if done runtime) finds the appropriate methods and their parameter list and sees if the parameter is a functional interface and if it is it creates an anonymous implementation of that interface. Technically (in byte code) it's different from an anonymous class, but otherwise identical (you won't see Main$1.class files).
Your example code (courtesy of Netbeans) can also be replaced with
SwingUtilities.invokeLater(MainAppJFrame::new);
Btw. :)
Lambda Expressions are basically adopted in Java 8 to simplify overriding process function as anonymous functions.
They are mere shortcut to Override old java anonymous functions.
Refer following example:
Suppose you have interface A which has only one method declared like below:
interface A{
void print();
}
now with old java style we'll override this in anonymous way like below:
new A() {
#Override
public void print() {
System.out.println("in a print method");
}
};
additionally now with java 8 lambda expression we'll use it like below:
() -> System.out.println("in a print method");
Here we can pass parameters required to method before -> operator
and then overridden body after -> operator.
the only more settings that we need to achieve this is that we need to declare interface with #FunctionalInterface as below:
#FunctionalInterface
interface A{
void print();
}
Note: - A lambda expression can only be used for a "functional" interface that has only one non-default method.
The syntax is confusing.
It drives me around the twist.
If it was not for Intellij, correcting me I would get it wrong.
Compiles OK.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> {return (integer%2 == 0);};
}
}
Compiles OK.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> {return integer%2 == 0;};
}
}
Does NOT Compile, since it is not a statement anymore.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> {return integer%2 == 0};
}
}
Does NOT Compile, since it is not a statement anymore and the return statement has been removed.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> {integer%2 == 0};
}
}
Compiles OK.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> integer%2 == 0;
}
}
So moral of the story is, if you use the brackets what is inside must
be a statement, and it must return the type expected by the Functional interface single abstract method (i.e. the only one that is not a default).
I actually wrote it more for myself than anything else, cause it was bugging me.

Declaring class inside a method - Final keyword [duplicate]

This question already has answers here:
Cannot refer to a non-final variable inside an inner class defined in a different method
(20 answers)
Why are only final variables accessible in anonymous class?
(15 answers)
Closed 9 years ago.
Given the following inner class (IsSomething) within a method:
public class InnerMethod {
private int x;
public class Something {
private int y;
public void printMyNumber(double x)
{
class IsSomething extends Something {
public void print() {
System.out.println(x);
}
}
}
}
}
Why does the X variable has to be FINAL to make it work..?
(I'm talking ofc about the X parameter of the "printMyNumber" function.)
The difference is between local variables vs class member variables. A member variable exists during the lifetime of the enclosing object, so it can be referenced by the inner class instance. A local variable, however, exists only during the method invocation, and is handled differently by the compiler, in that an implicit copy of it is generated as the member of the inner class. Without declaring the local variable final, one could change it, leading to subtle errors due to the inner class still referring to the original value of that variable.
Final local variables
There are two reasons I know for making a local variable or a
parameter final. The first reason is that you don't want your code
changing the local variable or parameter. It is considered by many to
be bad style to change a parameter inside a method as it makes the
code unclear. As a habit, some programmers make all their parameters
"final" to prevent themselves from changing them. I don't do that,
since I find it makes my method signature a bit ugly.
The second reason comes in when we want to access a local variable or
parameter from within an inner class. This is the actual reason, as
far as I know, that final local variables and parameters were
introduced into the Java language in JDK 1.1.
public class Access1 {
public void f() {
final int i = 3;
Runnable runnable = new Runnable() {
public void run() {
System.out.println(i);
}
};
}
}
Inside the run() method we can only access i if we make it final in the outer class. To understand the reasoning, we have to
look at what the compiler does. It produces two files, Access1.class
and Access1$1.class. When we decompile them with JAD, we get:
public class Access1 {
public Access1() {}
public void f() {
Access1$1 access1$1 = new Access1$1(this);
}
}
and
class Access1$1 implements Runnable {
Access1$1(Access1 access1) {
this$0 = access1;
}
public void run() {
System.out.println(3);
}
private final Access1 this$0;
}
Since the value of i is final, the compiler can "inline" it into the inner
class. It perturbed me that the local variables had to be final to be
accessed by the inner class until I saw the above.
When the value of the local variable can change for different
instances of the inner class, the compiler adds it as a data member of
the inner class and lets it be initialised in the constructor. The
underlying reason behind this is that Java does not have pointers, the
way that C has.
Consider the following class:
public class Access2 {
public void f() {
for (int i=0; i<10; i++) {
final int value = i;
Runnable runnable = new Runnable() {
public void run() {
System.out.println(value);
}
};
}
}
}
The problem here is that we have to make a new local data member each time we go through the for loop, so a thought I had today
while coding, was to change the above code to the following:
public class Access3 {
public void f() {
Runnable[] runners = new Runnable[10];
for (final int[] i={0}; i[0]<runners.length; i[0]++) {
runners[i[0]] = new Runnable() {
private int counter = i[0];
public void run() {
System.out.println(counter);
}
};
}
for (int i=0; i<runners.length; i++)
runners[i].run();
}
public static void main(String[] args) {
new Access3().f();
}
}
We now don't have to declare an additional final local variable. In fact, is it not perhaps true that
int[] i is like a common C pointer to an int? It took me 4 years to
see this, but I'd like to hear from you if you have heard this idea
somewhere else.
The methods in an anonymous class don't really have access to local variables and method parameters. Rather, when an object of the anonymous class is instantiated, copies of the final local variables and method parameters referred to by the object's methods are stored as instance variables in the object. The methods in the object of the anonymous class really access those hidden instance variables.
From the JLS :
Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final. Any local variable, used but not declared in an inner class must be definitely assigned (§16) before the body of the inner class.
This is because the lifetime of an instance of a local class can be much longer than the execution of the method in which the class is defined. For this reason, a local class must have a private internal copy of all local variables it uses (these copies are automatically generated by the compiler). The only way to ensure that the local variable and the private copy are always the same is to insist that the local variable is final.

Categories