Will methods in lambda only be evaluated when the lambda is executed? - java

Can we be sure that methods being called in a java lambda are only being called when the lambda itself is executed, and never in advance?
If you take a look at my code:
StringBuilder myStringBuilder = new StringBuilder("my result");
Supplier<String> mySupplier = () -> "result: " + myStringBuilder.toString();
myStringBuilder.append(", after appending.");
System.out.println(mySupplied.get());
Can we be 100% certain that the result will always be:
result: my result, after appending
And never just
result: my result

Consider the following snappet:
Runnable runnable = () -> expensiveMethod(); // Runnable not called
firstMethodCall(); // Runnable not called
secondMethodCall(); // Runnable not called
runnable.run(); // HERE IT COMES, Runnable IS called
The lambda expression is nothing else than the implementation of an anonymous class with one method (this secures #FunctionalInterface annotation).
Runnable runnable = new Runnable() {
void run() {
expensiveMethod();
}
};
// runnable's method is not executed since the method run is not called
// the runnable.run() invokes the expensiveMethod()
The Java 8 specification 15.27. Lambda Expressions explains that the expression is called when the appropriate method of the functional interface is invoked:
Evaluation of a lambda expression produces an instance of a functional interface (§9.8). Lambda expression evaluation does not cause the execution of the expression's body; instead, this may occur at a later time when an appropriate method of the functional interface is invoked.

Yes. The lambda code only executes when called not when the containing line is executed.

As per the spec
Lambda expression evaluation does not cause the execution of the expression's body; instead, this may occur at a later time when an appropriate method of the functional interface is invoked.

Lambda is like implementation code of an interface and just like an interface implementation, it will only be executed when you call it.

Lamba is an implementation of a Functional Interface. Its content will be changed / computed at the time of its call.
So, yes, you can 100% be sure about your assumption :)

Related

What is the background behind the following statement "A lambda is an object without an identity" in Java 8?

Would appreciate any help on understanding below two concepts in Java 8.
What I know
A lambda is an object without an identity and should not be used as a regular object.
A lambda expression should not be calling methods from Object class like toString, equals, hashCode etc.
What I'd like know more about
What difference does lambda expression have to be called as an object without identity?
Why exactly should methods from Objectclass not be used while using lambda expression?
1) A lambda is an object without an identify and should not be used as a regular object.
This is not true. A lambda is a Java object, and it does have an identity1. The problem is that the lifecycle is deliberately left specified to allow Java compilers freedom to optimize the code that evaluates them. Therefore, you cannot know when new lambda objects are going to be created, or existing ones are going to be reused.
JLS 15.27.4 says:
"At run time, evaluation of a lambda expression is similar to evaluation of a class instance creation expression, insofar as normal completion produces a reference to an object. Evaluation of a lambda expression is distinct from execution of the lambda body.
Either a new instance of a class with the properties below is allocated and initialized, or an existing instance of a class with the properties below is referenced. ... "
2) A lambda expression should not be calling methods from Object class like toString, equals, hashCode etc.
As written, that is also not true. A lambda expression may call those methods. However, it is not advisable to rely on those methods to have any specific behavior when you call them on a lambda object
The JLS states:
"The class ... may override methods of the Object class."
In other words, it may ... or may not ... override them. If you rely a particular behavior of these methods, your application is (in theory) non-portable.
Furthermore, since the instantiation semantics are also unspecified, the behavior of Object::equals and Object::hashCode are uncertain.
Finally, it is unspecified whether lambdas are clonable.
1 - Sure, a lambda doesn't have a name: it is anonymous. But name and identity are different concepts.
Basically, a lambda is a convenience of doing this:
#FunctionalInterface
interface A {
void b();
}
void c(A a) {
...
}
void main() {
c(new A() {
void b() {
...
}
});
}
I apologize for the less than stellar variable names, but as you can see, A is an interface with one method. c is a method that takes in an A interface. However, instead of creating your own class that implements A, you can create it on the spot. This is what you call an anonymous class, since it doesn't have a name. This is where the quote you have:
A lambda is an object without an identify
comes from. The class doesn't have an identity. The reason it relates to lambdas is because if an interface has only one method, you can use lamdas to simplify it.
void main() {
c(
() -> {
...
}
);
}
This is the exact same as before.
The second part, why lambdas shouldn't use Object's methods, I didn't know before. You should probably have someone else answer this, however my guess is that lambda classes don't look like it extends Object directly, so you can't use it's methods.

Execute runnables in a list

I have a list of runnables that I would like to call using lambda expressions:
Arrays.asList(runnable1, runnable2, runnable3, ...).forEach(r->r.run());
Is there a 'better' (more efficient) shortcut to call the Runnables run() method other than the following way?
Arrays.asList(runnable1, runnable2, runnable3, ...).forEach(Runnable::run);
I think this expression will be translated to a Runnable wrapping the runnable instance in the list.
EDIT:
My assumption/concern (maybe wrong) is that the compiler will translate the expression list.forEach(Runnable::run) to something like this, and thus not 'efficient':
list.forEach(r -> new Runnable() {
#Override
public void run() {
r.run();
}
});
Whether you write
Arrays.asList(runnable1, runnable2, runnable3, ...).forEach(r->r.run());
or
Arrays.asList(runnable1, runnable2, runnable3, ...).forEach(Runnable::run);
in either case, there will be an instance of Consumer generated, as that’s what Iterable.forEach expects.
The consumer will be equivalent to
Arrays.asList(runnable1, runnable2, runnable3, ...).forEach(new Consumer<Runnable>() {
public void accept(Runnable r) {
r.run();
}
});
but that’s not a wrapper around a runnable, as it encapsulates an action applied to arbitrary Runnable instances passed in as parameter. Hence, there is at most one Consumer instance created for the entire forEach operation.
As explained in this answer, the JVM will be responsible for the creation of the Consumer instance and has the freedom to reuse existing instances, which happens in practice with the current implementation and non-capturing instances of functional interfaces, which applies to both variants, using a lambda expression or a method reference, so there will be only one Consumer instance, reused even on subsequent evaluations of the statement.
The only difference with current compilers is that the lambda expression r->r.run() will generate a method within your class calling the run() method whereas for the method reference, the runtime generated Consumer implementation class will call it directly, which makes the method reference more efficient on the hard-to-ever-measure scale.

Lambda: Callable variable initiated with a Runnable instance

Just found a strange and interesting Lambda behavior.
Let's have the following class:
private class Task implements Runnable {
#Override
public void run() {
// something to process
}
}
The following statement is compiling and running:
Callable task = Task::new;
Could somebody explain why this is possible ?
EDIT:
Based on answers below, check the following statements:
1.
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(Task::new);
2.
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new Task());
On the first glance, seems the same, but actually does a totally different thing.
What happens here is exactly the above situation.
The reason is that ExecutorService has two methods:
submit(Runnable);
submit(Callable);
So, using the code from 1. the executor will process the following on it's internal thread:
new Task()
The version from 2. will actually call the submit(Runnable) method and the code from Task.run will be executed.
Conclusion: just be careful with Lambdas :)
The Callable is not initialized with a Runnable instance, it is initialized with a method reference to the Task constructor that will produce a Runnable when executed.
In other words, if you execute that Callable, it will return a new Task object that has not yet been run. That Task implements Runnable is actually completely irrelevant here.
This would be clearer if you didn't use the raw type. Task::new can be assigned to Callable<Task> because it is something that takes no parameters and returns a Task.
To implement the Callable<V> interface one must implement a method with the signature V call().
Therefore, you can implement this interface with method references of any methods that take nothing and return some reference type, which includes constructor method references such as Task::new.
In fact, any class having a parameter-less constructor can be used this way:
Callable<SomeClass> callable = SomeClass::new;

How does forEach() method works in Java 8

I am writing a snippet:
List<Integer> list=Arrays.toList(2,4,6,8);
list.forEach(i -> System.out.println(i));
Please explain me the flow of method call in the above snippet. How the forEach() method is passing the parameters to the accept() method? Does the forEach() method calls the accept method each time?
Please correct me if I am wrong.
i-> System.out.println(i)
returns an object of Consumer interface. forEach() calls the accept() method of that object with i as the parameter.
Because Consumer is a functional interface, your lambda function can implicitly satisfy it. So when you do
list.forEach(i -> System.out.println(i));
what you're doing conceptually (more below) is
list.forEach(new Consumer<String>() {
#Override
public void accept(String i) {
System.out.println(i);
}
});
The instance is then passed into forEach, which calls its accept method for each entry in the list.
From a comment you made on the question:
I am confused which method is invoked first. Is it the "forEach()" or the "accept ()" because both of them are working togather!
The order of things is:
An instance of the anonymous class is created (in effect, via the invokedynamic operation)
forEach is called, passing in that reference
forEach's code calls accept repeatedly, each time passing one of the list items into it (which it receives as i)
Note I said conceptually. An anonymous class isn't really created by the compiler; instead, a new bytecode operation called invokedynamic is used to create the consumer instance.

runnable future interface definition (jdk)

I have a question about the "correctness" of the RunnableFuture interface's definition. This may be a question about the correct contention for defining interfaces comments in java.
The definition of the RunnableFuture's run() method:
Sets this Future to the result of its computation ...
However, this clearly cannot be always true, since run()'s return type is void, and RunnableFuture is but an interface, it seems that if we were to gaurantee this, we would have to know something about the nature of the implementing class (the get() implementation, for example).
Now, if the RunnableFuture actually returned a value, which was hidden and always returned by an otherwise blocking get() function, such a definition (which would have to occur in a class, rather than an interface, due to its implementation restriction), would clearly be appropriate.
Thus, I am wondering: is the run() method for this interface correctly defined ?
As a counterexample: the Runnable run() interface definition is always correct.
When an object implementing interface Runnable is used to create a
thread, starting the thread causes the object's run method to be
called in that separately executing thread.
Thus, even though Runnable defines no implementation - the interface tells us how the JVM implements threads via the Runnable interface, without unnecessarily imposing non-gauranteed contract on implementing classes.
So I have 3 questions:
Is the documentation for RunnableFuture capable of being incorrect for several cases ?
If (1) is the case, is that acceptable via java conventions?
What is the "real" difference between a RunnableFuture run() and a Runnable run(), if any ?
See http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html
The contract of RunnableFuture is implemented by FutureTask. When you create a FutureTask, you provide either a Callable or a Runnable and a value. The run method of FutureTask looks something like:
public void run() {
V result;
try {
if(callable) {
result = callable.call();
} else {
runnable.run();
result = value;
}
} catch (Throwable t) {
setException(t);
return;
}
set(result);
}
Except the actual implementation wraps the Runnable-value pair in a Callable and does some extra checks to ensure the FutureTask is in the correct state before run is invoked.

Categories

Resources