Lambda Expressions in Java8 - java

import java.util.concurrent.Callable;
public class AdvancedLambda {
static void invoke(Runnable r){
r.run();
}
static Object invoke(Callable c) throws Exception {
return c.call();
}
public static void main(String[] args) throws Exception {
String s = (String) invoke(() -> true);
System.out.println(s);
}
}
Can anyone help me understand this? I was under the impression that we can only use lamba expressions in Java 8 only when we implement an interface and override its methods (replacing Anonymous classes by Lambda expressions).
Also in which situation will the method invoke(Runnable r) be called?

In the following line
String s = (String) invoke(() -> true);
It is actually invoke(Callable) that is getting called. The reason is:
() -> true is a lambda expression that has zero formal parameter and return a result.
Such a signature (zero parameter, single result) is compatible with the functional method call() of the Callable interface. Note that the interface does not need to have the #FunctionalInterface annotation, it just needs to have a single abstract method.
If you want to invoke invoke(Runnable) instead, you will need to create a lambda that is compatible with a functional method that takes zero parameter and returns no result (i.e. conforms with the signature of run()). Something like this:
invoke(() -> System.out.println("foo"));
Which just prints foo when ran.

A lambda expression supplies an implementation for a functional interface. This is what your code snippet does.
Your call to invoke passes a lambda expression with no arguments that returns a value (a boolean in your case). Therefore it matches Object invoke(Callable c), and not void invoke(Runnable r) (since a Callable's call method has a return value while a Runnable's run method doesn't return anything).
invoke(() -> {System.out.println("something");});
will call void invoke(Runnable r), since in this case the lambda expression has no return type.

only when we Implement a interface and override its methods
That's, more or less, what you do here. Not methods, but just one method: call(). This () -> true part is your implementation of Callable#call().
In other words, this line:
String s = (String) invoke(() -> true);
would be totally equivalent with this one:
String s = (String) invoke(new Callable() {
#Override
public Object call() throws Exception {
return true;
}
});

LambdaParameters -> LambdaBody
The arrow operator (->) for defining lambda functions
Lambda :can only be used to execute background tasks (here compiler then figures out)
Expressions : are return a value of some kind
Lambda expression is another way of writing an instance of anonymous class, to make an instance of anonymous class easier to write. In JVM, it will not occupy much memory as comparing with normal java object creation with new(executing static variables, static blocks, loading classes from whole hierarchy ).
Lambda expression syntax:
(params) -> expression to implement a #FunctionalInterface
In your test case: String s = (String) invoke(() -> true); the expression has return type true with no argument. So the Runnable FunctionalInterface does not match with lambda expression because it has void run() attribute. It matches with Callable FuncationalInterface using
V call().
How lambda expressions work under the hood?
It might look like the lambda expressions are just the syntax sugar for anonymous inner classes, but there is much more elegant approach. The simplest explanation is: the lambda expression is represented by a new method, and it is invoked at run-time using invokedynamic.
Source Code:
class LambdaExample {
public void abc() {
Runnable r = () -> {
System.out.println("hello");
}
r.run();
}
}
Bytecode equivalent:
class LambdaExample {
public void abc() {
Runnable r = <lambda$1 as Runnable instance>;
r.run();
}
static void lambda$1() {
System.out.println("hello");
}
}
Inside the JVM, there is a lambda factory that creates an instance of the functional interface (e.g. Runnable) from the generated lambda method (e.g. lambda$1).
Lambda expressions are great, and there's even more great stuff in Java 8...

Take a look at below example.
import javafx.beans.DefaultProperty;
import jdk.nashorn.internal.codegen.CompilerConstants;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Created by KUMAJYE on 13/09/2016.
*/
public class ThreadMonitor {
private static int noOfThreads = 0;
public static void main(String[] args) {
ThreadModel threadModel;
noOfThreads = Integer.parseInt(args[0]);
if (noOfThreads > 0) {
threadModel = getThreadingModelForCallsInCallingThread();
} else {
threadModel = getAsynchThreadingModel();
}
}
public static ThreadModel getThreadingModelForCallsInCallingThread() {
ExecutorService executor = Executors.newFixedThreadPool(noOfThreads);
return (r) -> executor.submit(r);
}
public static ThreadModel getAsynchThreadingModel() {
// do execution on same Thread or separate Thread.
// or
// r.run();
return (r) -> new Thread(r).start();
}
interface ThreadModel {
void invoke(Runnable r);
}
}

Related

Java Supplier<> defined as lambda. Need help understanding how this code even runs

Sorry for the somewhat unclear title but hopefully you'll see soon that it wasn't so easy to come up with a better one :)
So I have this interface that extends the Java Supplier #FunctionalInterface by defining one new method and also a default implementation of the Supplier.get() method. My default impl of .get() only wraps a call to the other method in some exception handling.
Then in my code I have different "versions" of this Supplier initialized using lambda notation.
Ex: SomeSupplier s = () -> doSomething();
Not sure why I even tried this because logically I don't understand how this even works, which it does. In my mind when I define my supplier using lambda like this I'm essentially overriding the Supplier.get() method. So how is it that in practice it seems to override my SomeSupplier.getSome() method? And leave the default impl of the .get() method intact?
What am I missing here?
Working example code:
public static void main(String[] args) throws InterruptedException {
SomeSupplier s = () -> getSomeOrException(); // "implements" the Supplier.get(), right?
for (int i = 0; i < 100; i++) {
System.out.println(s.get()); // => "Some!" or "null"
Thread.sleep(2);
}
}
private static String getSomeOrException() throws SomeCheckedException {
if (System.currentTimeMillis() % 10 == 0) {
throw new SomeCheckedException("10 %!");
}
return "Some!";
}
private interface SomeSupplier extends Supplier<String> {
#Override
default String get() {
try {
return getSome();
}
catch (SomeCheckedException e) {
return e.getMessage();
}
}
String getSome() throws SomeCheckedException; // How is this overridden/implemented?
}
private static class SomeCheckedException extends Exception {
public SomeCheckedException(String message) {
super(message);
}
}
}```
Your mistake is that assuming that if a Lambda of a Supplier implements get then a lambda of a SomeSupplier must also implement get.
But instead a Lambda will always implement the single abstract method of an interface* it's about to implement. In Supplier that's get. Your SomeSupplier however has implemented get (with a default method). Therefore getSome() becomes the single abstract method of the functional interface SomeSupplier. So this line:
SomeSupplier s = () -> getSomeOrException();
is roughly analogous to this:
SomeSupplier s = new SomeSupplier() {
String getSome() throws SomeCheckedException() {
return getSomeOrException();
}
};
Note that this implements getSome and not the underlying get method.
*: This is also why functional interfaces can only ever have one abstract method: there's no fallback logic to pick one option if more than one such method exists for a given target type.

Java Compile Error: Method reference in combination with overloading

I have the following class with an overloaded method:
import java.util.ArrayList;
import java.util.concurrent.Callable;
public abstract class Test {
public void test1 () {
doStuff (ArrayList::new); // compilation error
}
public void test2 () {
doStuff ( () -> new ArrayList<> ());
}
public abstract void doStuff (Runnable runable);
public abstract void doStuff (Callable<ArrayList<String>> callable);
}
The method test1 results in a compilation error with the error message
The method doStuff(Runnable) is ambiguous for the type Test.
I've added a third method test3 which looks like this:
public void test3 () {
doStuff ( () -> {
new ArrayList<> ();
});
}
Here the method doStuff(Runnable) is executed which is obvious.
But how does the compiler decide which of the two methods is executed in test2?
Why can I use the lambda expression but not the method reference?
The lambda expression in test2 useses the method which returns the callable, why does the method reference try to use the other method?
This seems to me like a java bug.
Edit:
It has nothing to do with the ArrayList and/or the generic type of it. Same error when you have Callable<String> or any other object.
Thanks in advance
Dimitri
Well, we can simplify this:
// takes a Runnable
public static void doStuff(Runnable runable) {
System.out.println("Runnable");
}
// takes a Callable
public static void doStuff(Callable<List<String>> callable) {
System.out.println("Callable");
}
And two extra methods that are overloads.
private static List<String> go() {
return null;
}
private static List<String> go(int i) {
return null;
}
What do you think will happen if you call this:
doStuff(YourClass::go);
Yeah... this will fail to match. And you might think that this is stupid as it only makes sense that go is the one that takes no arguments, it is easy for you in this simple situation to make this judgment, it's not for the compiler. In essence this is like a dead-lock:
In order to know which doStuff method to call, we need to know which go to call; and at the same time to understand which go to call we need to know which doStuff to call, or:
we need to resolve the method in order to find the target type, but we need to know the target type in order to resolve the method.
Same thing happens in your case with ArrayList having more than one constructors...
But how does the compiler decide which of the two methods is executed in test2?
public void test2 () {
doStuff ( () -> new ArrayList<> ());
}
is implicitly
public void test2 () {
doStuff ( () -> { return new ArrayList<>(); } );
}
and only Callable returns an object.
Why can I use the lambda expression but not the method reference?
It could be
public void test2 () {
doStuff ( () -> { new ArrayList<>(); } );
}
EDITED
Look at those examples:
Runnable r = ArrayList::new; // compiled
Callable c = ArrayList::new; // compiled
doStuff(ArrayList::new); // compile error, ambiguous
So ArrayList::new is interpreted as both Runnable and Callable. Note there is no lambda involved.
Next example:
Runnable r = () -> new ArrayList<>(); // compiled
Callable c = () -> new ArrayList<>(); // compiled
doStuff(() -> new ArrayList<>()); // compiled, the Callable one
When passing () -> new ArrayList<>() to a method
() -> { return new ArrayList<>(); }
is preferred than
() -> { new ArrayList<>(); }
So, the Callable one is invoked and there is nothing ambiguous.

Why does a lambda change overloads when it throws a runtime exception?

Bear with me, the introduction is a bit long-winded but this is an interesting puzzle.
I have this code:
public class Testcase {
public static void main(String[] args){
EventQueue queue = new EventQueue();
queue.add(() -> System.out.println("case1"));
queue.add(() -> {
System.out.println("case2");
throw new IllegalArgumentException("case2-exception");});
queue.runNextTask();
queue.add(() -> System.out.println("case3-never-runs"));
}
private static class EventQueue {
private final Queue<Supplier<CompletionStage<Void>>> queue = new ConcurrentLinkedQueue<>();
public void add(Runnable task) {
queue.add(() -> CompletableFuture.runAsync(task));
}
public void add(Supplier<CompletionStage<Void>> task) {
queue.add(task);
}
public void runNextTask() {
Supplier<CompletionStage<Void>> task = queue.poll();
if (task == null)
return;
try {
task.get().
whenCompleteAsync((value, exception) -> runNextTask()).
exceptionally(exception -> {
exception.printStackTrace();
return null; });
}
catch (Throwable exception) {
System.err.println("This should never happen...");
exception.printStackTrace(); }
}
}
}
I am trying to add tasks onto a queue and run them in order. I was expecting all 3 cases to invoke the add(Runnable) method; however, what actually happens is that case 2 gets interpreted as a Supplier<CompletionStage<Void>> that throws an exception before returning a CompletionStage so the "this should never happen" code block gets triggered and case 3 never runs.
I confirmed that case 2 is invoking the wrong method by stepping through the code using a debugger.
Why isn't the Runnable method getting invoked for the second case?
Apparently this issue only occurs on Java 10 or higher, so be sure to test under this environment.
UPDATE: According to JLS §15.12.2.1. Identify Potentially Applicable Methods and more specifically JLS §15.27.2. Lambda Body it seems that () -> { throw new RuntimeException(); } falls under the category of both "void-compatible" and "value-compatible". So clearly there is some ambiguity in this case but I certainly don't understand why Supplier is any more appropriate of an overload than Runnable here. It's not as if the former throws any exceptions that the latter does not.
I don't understand enough about the specification to say what should happen in this case.
I filed a bug report which is visible at https://bugs.openjdk.java.net/browse/JDK-8208490
The problem is that there are two methods:
void fun(Runnable r) and void fun(Supplier<Void> s).
And an expression fun(() -> { throw new RuntimeException(); }).
Which method will be invoked?
According to JLS §15.12.2.1, the lambda body is both void-compatible and value-compatible:
If the function type of T has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).
If the function type of T has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).
So both methods are applicable to the lambda expression.
But there are two methods so java compiler needs to find out which method is more specific
In JLS §15.12.2.5. It says:
A functional interface type S is more specific than a functional interface type T for an expression e if all of the following are true:
One of the following is:
Let RS be the return type of MTS, adapted to the type parameters of MTT, and let RT be the return type of MTT. One of the following must be true:
One of the following is:
RT is void.
So S (i.e. Supplier) is more specific than T (i.e. Runnable) because the return type of the method in Runnable is void.
So the compiler choose Supplier instead of Runnable.
First, according to §15.27.2 the expression:
() -> { throw ... }
Is both void-compatible, and value-compatible, so it's compatible (§15.27.3) with Supplier<CompletionStage<Void>>:
class Test {
void foo(Supplier<CompletionStage<Void>> bar) {
throw new RuntimeException();
}
void qux() {
foo(() -> { throw new IllegalArgumentException(); });
}
}
(see that it compiles)
Second, according to §15.12.2.5 Supplier<T> (where T is a reference type) is more specific than Runnable:
Let:
S := Supplier<T>
T := Runnable
e := () -> { throw ... }
So that:
MTs := T get() ==> Rs := T
MTt := void run() ==> Rt := void
And:
S is not a superinterface or a subinterface of T
MTs and MTt have the same type parameters (none)
No formal parameters so bullet 3 is also true
e is an explicitly typed lambda expression and Rt is void
It appears that when throwing an Exception, the compiler chooses the interface which returns a reference.
interface Calls {
void add(Runnable run);
void add(IntSupplier supplier);
}
// Ambiguous call
calls.add(() -> {
System.out.println("hi");
throw new IllegalArgumentException();
});
However
interface Calls {
void add(Runnable run);
void add(IntSupplier supplier);
void add(Supplier<Integer> supplier);
}
complains
Error:(24, 14) java: reference to add is ambiguous
both method add(java.util.function.IntSupplier) in Main.Calls and method add(java.util.function.Supplier) in Main.Calls match
Lastly
interface Calls {
void add(Runnable run);
void add(Supplier<Integer> supplier);
}
compiles fine.
So weirdly;
void vs int is ambiguous
int vs Integer is ambiguous
void vs Integer is NOT ambiguous.
So I figure something is broken here.
I have sent a bug report to oracle.
First things first:
The key point is that overloading methods or constructors with
different functional interfaces in the same argument position causes
confusion. Therefore, do not overload methods to take different
functional interfaces in the same argument position.Joshua Bloch, - Effective Java.
Otherwise, you'll need a cast to indicate the correct overloading:
queue.add((Runnable) () -> { throw new IllegalArgumentException(); });
^
The same behavior is evident when using an infinite loop instead of a runtime exception:
queue.add(() -> { for (;;); });
In the cases shown above, the lambda body never completes normally, which adds to the confusion: which overload to choose (void-compatible or value-compatible) if the lambda is implicitly typed? Because in this situation both methods become applicable, for example you can write:
queue.add((Runnable) () -> { throw new IllegalArgumentException(); });
queue.add((Supplier<CompletionStage<Void>>) () -> {
throw new IllegalArgumentException();
});
void add(Runnable task) { ... }
void add(Supplier<CompletionStage<Void>> task) { ... }
And, like stated in this answer - the most specific method is chosen in case of ambiguity:
queue.add(() -> { throw new IllegalArgumentException(); });
↓
void add(Supplier<CompletionStage<Void>> task);
At the same time, when the lambda body completes normally (and is void-compatible only):
queue.add(() -> { for (int i = 0; i < 2; i++); });
queue.add(() -> System.out.println());
the method void add(Runnable task) is chosen, because there is no ambiguity in this case.
As stated in the JLS §15.12.2.1, when a lambda body is both void-compatible and value-compatible, the definition of potential applicability goes beyond a basic arity check to also take into account the presence and shape of functional interface target types.
I wrongly considered this a bug, but it appears to be correct according to §15.27.2. Consider:
import java.util.function.Supplier;
public class Bug {
public static void method(Runnable runnable) { }
public static void method(Supplier<Integer> supplier) { }
public static void main(String[] args) {
method(() -> System.out.println());
method(() -> { throw new RuntimeException(); });
}
}
javac Bug.java
javap -c Bug
public static void main(java.lang.String[]);
Code:
0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
5: invokestatic #3 // Method add:(Ljava/lang/Runnable;)V
8: invokedynamic #4, 0 // InvokeDynamic #1:get:()Ljava/util/function/Supplier;
13: invokestatic #5 // Method add:(Ljava/util/function/Supplier;)V
16: return
This happens with jdk-11-ea+24, jdk-10.0.1, and jdk1.8u181.
zhh's answer led me to find this even simpler test case:
import java.util.function.Supplier;
public class Simpler {
public static void main(String[] args) {
Supplier<Integer> s = () -> { throw new RuntimeException(); };
}
}
However, duvduv pointed out §15.27.2, in particular, this rule:
A block lambda body is value-compatible if it cannot complete normally (§14.21) and every return statement in the block has the form return Expression;.
Thus, a block lambda is trivially value-compatible even if it contains no return statement at all. I would have thought, because the compiler needs to infer its type, that it would require at least one return Expression;. Holgar and others have pointed out that this is not necessary with ordinary methods such as:
int foo() { for(;;); }
But in that case the compiler only needs to ensure there is no return that contradicts the explicit return type; it doesn't need to infer a type. However, the rule in the JLS is written to allow the same freedom with block lambdas as with ordinary methods. Perhaps I should have seen that sooner, but I did not.
I filed a bug with Oracle but have since sent an update to it referencing §15.27.2 and stating that I believe my original report to be in error.

How to chain BiFunctions?

I would like to chain BiFunctions, like in the method chainWanted in the code sample below.
BiFunction takes Function as a parameter of AndThen. is it possible to somehow chain BiFunctions ?
The code here doesn't compile because of this and I cannot cast BiFunction to Function.
import java.util.function.BiFunction;
import java.util.function.Function;
import org.openqa.selenium.remote.RemoteWebDriver;
public class Wf {
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> init = this::init;
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> wait = this::wait;
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainNow = init
.andThen(d -> {
System.out.println("--------------");
return null;
});
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = init
.andThen((BiFunction) wait);
public RemoteWebDriver init(RemoteWebDriver d, WfParams params) {
System.out.println("init(d, params)");
return d;
}
public RemoteWebDriver wait(RemoteWebDriver d, WfParams params) {
System.out.println("Wf.wait(d, params)");
return d;
}
public static void main(String[] args) throws Exception {
new Wf().start();
}
private void start() {
chainNow.apply(null, null);
}
}
Chaining of one Function to another works naturally because the return value of the first function is passed as the argument to the next function, and that function's return value is passed as the argument to the subsequent function, and so forth. This doesn't work naturally with BiFunction because they take two arguments. The first argument would be the return value from the previous function, but what would the second argument be? It also explains why BiFunction allows chaining with andThen to a Function instead of to another BiFunction.
This suggests, however, that it would be possible to chain one BiFunction to another if there were some way of providing the value for second argument. This can be done by creating a helper function that stores the value for the second argument in a local variable. Then, a BiFunction can be converted into a Function by capturing that local variable from the environment and using it as the second argument.
Here's what that would look like.
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = this::chainHelper;
RemoteWebDriver chainHelper(RemoteWebDriver driver, WfParams params) {
return
init.andThen(rwd -> wait.apply(rwd, params))
.apply(driver, params);
}
// ...
chainWanted.apply(driver, params);
The chainHelper method holds the params argument for later capture. We call init.andThen() in order to do the chaining. But this requires a Function whereas wait is a BiFunction. Instead of using a method reference this::wait we use the lambda expression
rwd -> wait.apply(rwd, params)
which captures params from the lexical environment. This gives a lambda expression that takes a single argument and returns a single value, so it's now a Function that wraps the wait which is a BiFunction. This is an example of partial application or currying. Finally, we call the resulting BiFunction using apply(), passing the original arguments.
Where should the WfParams come from for the invocation of wait? If you mean to reuse the same WfParams for all the functions calls, just put WfParams as a class member variable instead of passing it to each function.
class Wf {
private final WfParams params;
public Wf(WfParams params) {
this.params = params;
}
UnaryOperator<RemoteWebDriver> init = this::init;
UnaryOperator<RemoteWebDriver> wait = this::wait;
Function<RemoteWebDriver,RemoteWebDriver> chain = init.andThen(wait);
RemoteWebDriver init(RemoteWebDriver d) {
// can use WfParams here
return d;
}
RemoteWebDriver wait(RemoteWebDriver d) {
// can use WfParams here
return d;
}
private void start() {
chain.apply(null);
}
public static void main(String[] args) {
new Wf(new WfParams()).start();
}
}
Is there a particular reason you want to use function chaining like that? Why not simply call init(...); wait(...); from start()?
I did something like this - created my custom BiFunction.
The idea being:
Return type is same as the second argument
First argument is passed internally to chained biFunction
public interface BiFunctionCustom<T, U> extends BiFunction<T,U,U> {
default BiFunctionCustom<T, U> andThen(BiFunctionCustom<T, U> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(t, apply(t, u));
}
}

Java Pass Method as Parameter

I am looking for a way to pass a method by reference. I understand that Java does not pass methods as parameters, however, I would like to get an alternative.
I've been told interfaces are the alternative to passing methods as parameters but I don't understand how an interface can act as a method by reference. If I understand correctly an interface is simply an abstract set of methods that are not defined. I don't want to send an interface that needs to be defined every time because several different methods could call the same method with the same parameters.
What I would like to accomplish is something similar to this:
public void setAllComponents(Component[] myComponentArray, Method myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) { //recursive call if Container
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
} //end if node
myMethod(leaf);
} //end looping through components
}
invoked such as:
setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());
Edit: as of Java 8, lambda expressions are a nice solution as other answers have pointed out. The answer below was written for Java 7 and earlier...
Take a look at the command pattern.
// NOTE: code not tested, but I believe this is valid java...
public class CommandExample
{
public interface Command
{
public void execute(Object data);
}
public class PrintCommand implements Command
{
public void execute(Object data)
{
System.out.println(data.toString());
}
}
public static void callCommand(Command command, Object data)
{
command.execute(data);
}
public static void main(String... args)
{
callCommand(new PrintCommand(), "hello world");
}
}
Edit: as Pete Kirkham points out, there's another way of doing this using a Visitor. The visitor approach is a little more involved - your nodes all need to be visitor-aware with an acceptVisitor() method - but if you need to traverse a more complex object graph then it's worth examining.
In Java 8, you can now pass a method more easily using Lambda Expressions and Method References. First, some background: a functional interface is an interface that has one and only one abstract method, although it can contain any number of default methods (new in Java 8) and static methods. A lambda expression can quickly implement the abstract method, without all the unnecessary syntax needed if you don't use a lambda expression.
Without lambda expressions:
obj.aMethod(new AFunctionalInterface() {
#Override
public boolean anotherMethod(int i)
{
return i == 982
}
});
With lambda expressions:
obj.aMethod(i -> i == 982);
Here is an excerpt from the Java tutorial on Lambda Expressions:
Syntax of Lambda Expressions
A lambda expression consists of the following:
A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p,
which represents an instance of the Person class.Note: You
can omit the data type of the parameters in a lambda expression. In
addition, you can omit the parentheses if there is only one parameter.
For example, the following lambda expression is also valid:
p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
The arrow token, ->
A body, which consists of a single expression or a statement block. This example uses the following expression:
p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively,
you can use a return statement:
p -> {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have
to enclose a void method invocation in braces. For example, the
following is a valid lambda expression:
email -> System.out.println(email)
Note that a lambda expression looks a lot like a method declaration;
you can consider lambda expressions as anonymous methods—methods
without a name.
Here is how you can "pass a method" using a lambda expression:
interface I {
public void myMethod(Component component);
}
class A {
public void changeColor(Component component) {
// code here
}
public void changeSize(Component component) {
// code here
}
}
class B {
public void setAllComponents(Component[] myComponentArray, I myMethodsInterface) {
for(Component leaf : myComponentArray) {
if(leaf instanceof Container) { // recursive call if Container
Container node = (Container)leaf;
setAllComponents(node.getComponents(), myMethodInterface);
} // end if node
myMethodsInterface.myMethod(leaf);
} // end looping through components
}
}
class C {
A a = new A();
B b = new B();
public C() {
b.setAllComponents(this.getComponents(), component -> a.changeColor(component));
b.setAllComponents(this.getComponents(), component -> a.changeSize(component));
}
}
Class C can be shortened even a bit further by the use of method references like so:
class C {
A a = new A();
B b = new B();
public C() {
b.setAllComponents(this.getComponents(), a::changeColor);
b.setAllComponents(this.getComponents(), a::changeSize);
}
}
Since Java 8 there is a Function<T, R> interface (docs), which has method
R apply(T t);
You can use it to pass functions as parameters to other functions. T is the input type of the function, R is the return type.
In your example you need to pass a function that takes Component type as an input and returns nothing - Void. In this case Function<T, R> is not the best choice, since there is no autoboxing of Void type. The interface you are looking for is called Consumer<T> (docs) with method
void accept(T t);
It would look like this:
public void setAllComponents(Component[] myComponentArray, Consumer<Component> myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) {
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
}
myMethod.accept(leaf);
}
}
And you would call it using method references:
setAllComponents(this.getComponents(), this::changeColor);
setAllComponents(this.getComponents(), this::changeSize);
Assuming that you have defined changeColor() and changeSize() methods in the same class.
If your method happens to accept more than one parameter, you can use BiFunction<T, U, R> - T and U being types of input parameters and R being return type. There is also BiConsumer<T, U> (two arguments, no return type). Unfortunately for 3 and more input parameters, you have to create an interface by yourself. For example:
public interface Function4<A, B, C, D, R> {
R apply(A a, B b, C c, D d);
}
Use the java.lang.reflect.Method object and call invoke
First define an Interface with the method you want to pass as a parameter
public interface Callable {
public void call(int param);
}
Implement a class with the method
class Test implements Callable {
public void call(int param) {
System.out.println( param );
}
}
// Invoke like that
Callable cmd = new Test();
This allows you to pass cmd as parameter and invoke the method call defined in the interface
public invoke( Callable callable ) {
callable.call( 5 );
}
While this is not yet valid for Java 7 and below, I believe that we should look to the future and at least recognize the changes to come in new versions such as Java 8.
Namely, this new version brings lambdas and method references to Java (along with new APIs, which are another valid solution to this problem. While they still require an interface no new objects are created, and extra classfiles need not pollute output directories due to different handling by the JVM.
Both flavors(lambda and method reference) require an interface available with a single method whose signature is used:
public interface NewVersionTest{
String returnAString(Object oIn, String str);
}
Names of methods will not matter from here on. Where a lambda is accepted, a method reference is as well. For example, to use our signature here:
public static void printOutput(NewVersionTest t, Object o, String s){
System.out.println(t.returnAString(o, s));
}
This is just a simple interface invocation, up until the lambda1 gets passed:
public static void main(String[] args){
printOutput( (Object oIn, String sIn) -> {
System.out.println("Lambda reached!");
return "lambda return";
}
);
}
This will output:
Lambda reached!
lambda return
Method references are similar. Given:
public class HelperClass{
public static String testOtherSig(Object o, String s){
return "real static method";
}
}
and main:
public static void main(String[] args){
printOutput(HelperClass::testOtherSig);
}
the output would be real static method. Method references can be static, instance, non-static with arbitrary instances, and even constructors. For the constructor something akin to ClassName::new would be used.
1 This is not considered a lambda by some, as it has side effects. It does illustrate, however, the use of one in a more straightforward-to-visualize fashion.
Last time I checked, Java is not capable of natively doing what you want; you have to use 'work-arounds' to get around such limitations. As far as I see it, interfaces ARE an alternative, but not a good alternative. Perhaps whoever told you that was meaning something like this:
public interface ComponentMethod {
public abstract void PerfromMethod(Container c);
}
public class ChangeColor implements ComponentMethod {
#Override
public void PerfromMethod(Container c) {
// do color change stuff
}
}
public class ChangeSize implements ComponentMethod {
#Override
public void PerfromMethod(Container c) {
// do color change stuff
}
}
public void setAllComponents(Component[] myComponentArray, ComponentMethod myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) { //recursive call if Container
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
} //end if node
myMethod.PerfromMethod(leaf);
} //end looping through components
}
Which you'd then invoke with:
setAllComponents(this.getComponents(), new ChangeColor());
setAllComponents(this.getComponents(), new ChangeSize());
If you don't need these methods to return something, you could make them return Runnable objects.
private Runnable methodName (final int arg) {
return (new Runnable() {
public void run() {
// do stuff with arg
}
});
}
Then use it like:
private void otherMethodName (Runnable arg){
arg.run();
}
Java-8 onwards
Java 8 onwards, you can provide the implementation of the abstract method of a functional interface (an interface that has only one abstract method) using a lambda expression and pass the same to a method as a parameter.
#FunctionalInterface
interface ArithmeticFunction {
public int calcualate(int a, int b);
}
public class Main {
public static void main(String args[]) {
ArithmeticFunction addition = (a, b) -> a + b;
ArithmeticFunction subtraction = (a, b) -> a - b;
int a = 20, b = 5;
System.out.println(perform(addition, a, b));
// or
System.out.println(perform((x, y) -> x + y, a, b));
System.out.println(perform(subtraction, a, b));
// or
System.out.println(perform((x, y) -> x - y, a, b));
}
static int perform(ArithmeticFunction function, int a, int b) {
return function.calcualate(a, b);
}
}
Output:
25
25
15
15
ONLINE DEMO
Learn more about it from Method References.
I didn't find any example explicit enough for me on how to use java.util.function.Function for simple method as parameter function. Here is a simple example:
import java.util.function.Function;
public class Foo {
private Foo(String parameter) {
System.out.println("I'm a Foo " + parameter);
}
public static Foo method(final String parameter) {
return new Foo(parameter);
}
private static Function parametrisedMethod(Function<String, Foo> function) {
return function;
}
public static void main(String[] args) {
parametrisedMethod(Foo::method).apply("from a method");
}
}
Basically you have a Foo object with a default constructor. A method that will be called as a parameter from the parametrisedMethod which is of type Function<String, Foo>.
Function<String, Foo> means that the function takes a String as parameter and return a Foo.
The Foo::Method correspond to a lambda like x -> Foo.method(x);
parametrisedMethod(Foo::method) could be seen as x -> parametrisedMethod(Foo.method(x))
The .apply("from a method") is basically to do parametrisedMethod(Foo.method("from a method"))
Which will then return in the output:
>> I'm a Foo from a method
The example should be running as is, you can then try more complicated stuff from the above answers with different classes and interfaces.
Java do have a mechanism to pass name and call it. It is part of the reflection mechanism.
Your function should take additional parameter of class Method.
public void YouMethod(..... Method methodToCall, Object objWithAllMethodsToBeCalled)
{
...
Object retobj = methodToCall.invoke(objWithAllMethodsToBeCalled, arglist);
...
}
I did not found any solution here that show how to pass method with parameters bound to it as a parameter of a method. Bellow is example of how you can pass a method with parameter values already bound to it.
Step 1: Create two interfaces one with return type, another without. Java has similar interfaces but they are of little practical use because they do not support Exception throwing.
public interface Do {
void run() throws Exception;
}
public interface Return {
R run() throws Exception;
}
Example of how we use both interfaces to wrap method call in transaction. Note that we pass method with actual parameters.
//example - when passed method does not return any value
public void tx(final Do func) throws Exception {
connectionScope.beginTransaction();
try {
func.run();
connectionScope.commit();
} catch (Exception e) {
connectionScope.rollback();
throw e;
} finally {
connectionScope.close();
}
}
//Invoke code above by
tx(() -> api.delete(6));
Another example shows how to pass a method that actually returns something
public R tx(final Return func) throws Exception {
R r=null;
connectionScope.beginTransaction();
try {
r=func.run();
connectionScope.commit();
} catch (Exception e) {
connectionScope.rollback();
throw e;
} finally {
connectionScope.close();
}
return r;
}
//Invoke code above by
Object x= tx(() -> api.get(id));
Example of solution with reflection, passed method must be public
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Program {
int i;
public static void main(String[] args) {
Program obj = new Program(); //some object
try {
Method method = obj.getClass().getMethod("target");
repeatMethod( 5, obj, method );
}
catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
System.out.println( e );
}
}
static void repeatMethod (int times, Object object, Method method)
throws IllegalAccessException, InvocationTargetException {
for (int i=0; i<times; i++)
method.invoke(object);
}
public void target() { //public is necessary
System.out.println("target(): "+ ++i);
}
}
Use the Observer pattern (sometimes also called Listener pattern):
interface ComponentDelegate {
void doSomething(Component component);
}
public void setAllComponents(Component[] myComponentArray, ComponentDelegate delegate) {
// ...
delegate.doSomething(leaf);
}
setAllComponents(this.getComponents(), new ComponentDelegate() {
void doSomething(Component component) {
changeColor(component); // or do directly what you want
}
});
new ComponentDelegate()... declares an anonymous type implementing the interface.
Here is a basic example:
public class TestMethodPassing
{
private static void println()
{
System.out.println("Do println");
}
private static void print()
{
System.out.print("Do print");
}
private static void performTask(BasicFunctionalInterface functionalInterface)
{
functionalInterface.performTask();
}
#FunctionalInterface
interface BasicFunctionalInterface
{
void performTask();
}
public static void main(String[] arguments)
{
performTask(TestMethodPassing::println);
performTask(TestMethodPassing::print);
}
}
Output:
Do println
Do print
I'm not a java expert but I solve your problem like this:
#FunctionalInterface
public interface AutoCompleteCallable<T> {
String call(T model) throws Exception;
}
I define the parameter in my special Interface
public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {.......
//call here
String value = getSearchText.call(item);
...
}
Finally, I implement getSearchText method while calling initialize method.
initialize(getMessageContactModelList(), new AutoCompleteCallable() {
#Override
public String call(Object model) throws Exception {
return "custom string" + ((xxxModel)model.getTitle());
}
})
I appreciate the answers above but I was able to achieve the same behavior using the method below; an idea borrowed from Javascript callbacks. I'm open to correction though so far so good (in production).
The idea is to use the return type of the function in the signature, meaning that the yield has to be static.
Below is a function that runs a process with a timeout.
public static void timeoutFunction(String fnReturnVal) {
Object p = null; // whatever object you need here
String threadSleeptime = null;
Config config;
try {
config = ConfigReader.getConfigProperties();
threadSleeptime = config.getThreadSleepTime();
} catch (Exception e) {
log.error(e);
log.error("");
log.error("Defaulting thread sleep time to 105000 miliseconds.");
log.error("");
threadSleeptime = "100000";
}
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() {
// Do job here using --- fnReturnVal --- and return appropriate value
return null;
}
};
Future<Object> future = executor.submit(task);
try {
p = future.get(Integer.parseInt(threadSleeptime), TimeUnit.MILLISECONDS);
} catch (Exception e) {
log.error(e + ". The function timed out after [" + threadSleeptime
+ "] miliseconds before a response was received.");
} finally {
// if task has started then don't stop it
future.cancel(false);
}
}
private static String returnString() {
return "hello";
}
public static void main(String[] args) {
timeoutFunction(returnString());
}

Categories

Resources