Are these methods of using event identical in JavaFX? [duplicate] - java

This question already has answers here:
Java8 Lambdas vs Anonymous classes
(9 answers)
Closed 3 years ago.
I have a button and I want a text to be displayed when I hover the mouse over the button.
Both of these work but can they be used interchangeably?
// First
EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
System.out.println("Hello World");
}
};
button.setOnMouseEntered(eventHandler);
// Second. Lambda expression.
button.setOnMouseEntered(e -> {
System.out.println("Hello ");
});
I don't quite understand the first one. I suppose that EventHandler<MouseEvent> is the type and eventHandler is the name of the object. Right?

Yes, they both will execute the same code.
The first one is an so-called anonymous class. This means that you override the methods (handle in this case) of the inherited interface directly without having to do that with additional classes/interfaces.
You then pass the handler instance to the setOnMouseEntered method.
The lambda expression does this also but since the method requires a certain object type, you can write it shorter with the lambda expression.
e is basically the same as eventHandler

The first one is an anonymous inner class, where the handle method is overridden. This was the way to do listeners and handlers before lambda expressions. Now, if the class is an functional interface (only 1 abstract method, like the EventHandler in your case with its only method, handle) then a lambda expression can be used instead of anonim class.
The two methods are indeed the same, but using lambdas are preferred, because the code will be much more compact and easier to understand.

Both of the answers already provided are good, but I wanted to add another consideration.
Whenever possible, lambdas are preferable, not only because they're easier to read, but they also result in very different bytecode when compiled.
In the first example, the compiler creates a separate class (for example: OuterClass$1). This class has to be instantiated on each invocation, which will have to be garbage collected at some point.
In the second example, the lambda is compiled to a method that's local to the containing class. This means that it's a just a simple method invocation.
Depending on how frequently it's invoked, this may be an important consideration.

I believe the first example could be explicitly written as:
private class MouseHandler implements EventHandler<MouseEvent> {
public void handle(MouseEvent e) {
System.out.println("Hello World");
}
}
button.setOnMouseEntered(new MouseHandler());
This can be reduced via the anonymous class and more by the lambda expression. My understanding is that this is only possible because EventHandler is a functional interface.
What is a functional interface in Java SKO

Related

Anonymous class can be replaced with lambda?

While i'm writing some code in intellij, it keeps popping up, says
Anonymous class can be replaced with lambda?
So what does that mean? what is lambda expression and how Anonymous class can be replaced with lambda?
Play.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JPanel playscreen = new JPanel();
playscreen.setBackground(Color.WHITE);
p.add(playscreen);
}
});
Anonymous new can be replaced with lambda ?
It's not 100% correct, Anonymous class for an interfaces having one abstract method can be replaced with lambda expression (which is called functional interface)
Since ActionListener has only one method actionPerformed(ActionEvent e) you can write it using lambda expression
Play.addActionListener((event) -> {
JPanel playscreen = new JPanel();
playscreen.setBackground(Color.WHITE);
p.add(playscreen);
});
Lambda Expressions
One issue with anonymous classes is that if the implementation of your anonymous class is very simple, such as an interface that contains only one method, then the syntax of anonymous classes may seem unwieldy and unclear. In these cases, you're usually trying to pass functionality as an argument to another method, such as what action should be taken when someone clicks a button. Lambda expressions enable you to do this, to treat functionality as method argument, or code as data.
FunctionalInterface
A functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.
Your code can be changed to this:
Play.addActionListener((event) -> {
JPanel playscreen = new JPanel();
playscreen.setBackground(Color.WHITE);
p.add(playscreen);
});
The reason you can do this is because ActionListener is a functional interface, meaning that it has exactly one abstract method that you must implement. A lambda is able to essentially take the place of that single function and act as an implementation of that interface.
The Lambda acts like the implementation of the method actionPerformed and (event) is the argument to that method and the -> { ... } is the body of that method.

Does lambda expression automatically create new object for its entry parameters?

I am new to functional programming, so far i have understood how to use it, anonymous function etc.
I saw many examples of code where the object needed as parameter in my lambda expression actually doesn't exist in that moment (it isn't instantiated).
For example, is this:
myClass.myMethod(c -> {my overridden code});
the same as this
myClass.myMethod(new String() -> {my overridden code});
considering that c is not declared in my code and myMethod correctly implements a functional interface which abstract method requires a String?
EDIT:
I got some problems with this question:
JavaFX ComboBox Image
With this part of code:
comboBox.setCellFactory(c -> new StatusListCell());
I can't figure out where c is taken from, it's not declared at all, that's why i was wondering if lambda expressions could create new objects automatically.
c is actually only a placeholder, like a parameter in a method would be (which does not differ from the functioning of the lambda here).
myClass.myMethod(c -> {my overridden code});
is the equivalent of the following
myClass.myMethod(new Consumer<String>(){
#Override
public void accept(String c) {
{my overridden code}
}
}
So the answer to your question is : No. The lambda represents a method, a function but is not an executable piece by itself, it has to be invoked with outside parameters.

Lambda expressions mechanisms in Java [duplicate]

This question already has answers here:
Lambda expression vs method reference implementation details
(3 answers)
Closed 5 years ago.
I just read in a book that when a lambda expression is assigned to a functional interface, then that sets the "target type" for the lambda and an instance of that type (that is, the functional interface's type) is created with the lambda expression used as implementation for the abstract method in the functional interface.
My question: If so, then does that mean lambdas aren't really standalone methods and as such a new type of element brought into the language, but are simply a more compact way for expressing an anonymous class and as such merely are added facility (just like generics) on the compiler's side?
Moreover, how do method references comply with that, in particular, static methods which are not associated with any objects? For example, when a method reference to an instance method is assigned to a functional interface then the encapsulating object for that method is used, but what happens in the case of a static method - those are not associated with any object.. ?
If so, then does that mean lambdas aren't really standalone methods and as such a new type of element brought into the language,
Correct, lambdas are compiled into normal methods with a synthetic name
but are simply a more compact way for expressing an anonymous class and as such merely are added facility (just like generics) on the compiler's side?
No, it's not only on the compiler side. There are is also code in the JVM involved, so that the compiler doesn't have to write class files for the lambdas.
Moreover, how do method references comply with that, in particular, static methods which are not associated with any objects?
Method references are not different from lambdas: at runtime there has to be an object implementing the functional interface. Upon calling the "SAM" of the object this method will call the referenced method.
For example, when a method reference to an instance method is assigned to a functional interface then the encapsulating object for that method is used,
No, it can't be used. Let's take the following example using a System.out::println method reference:
Arrays.asList("A", "B").forEach(System.out::println);
List<E>.forEach() expects a Consumer<? super E> which defines the method void accept(E e). The compiler need to generate byte code and other information in the class file so that at runtime the JVM can generate a class implementing Consumer<E> with a method void accept(E e). This generated method then calls System.out.println(Object o).
The runtime generated class would look something like
class $$lambda$xy implements Consumer<Object> {
private PrintStream out;
$$lambda$xy(PrintStream out) {
this.out = out;
}
void accept(Object o) {
out.println(o);
}
}
Your question from the comment: "Why not directly assign to instance and its method?"
Let's expand the example a little bit:
static void helloWorld(Consumer<String> consumer) {
consumer.apply("Hello World!");
}
public static void main(String[] args) {
helloWorld(System.out::println);
}
To compile this, the compiler has to generate bytecode that creates an object implementing Consumer<String> (so it can pass the object into helloWorld()). That object somehow has to store the information that upon calling it's accept(x) method it has to call println(x) on the System.out PrintStream.
Other languages may have other names or concepts for this kind of objects - in Java the established concept is "an anonymous class implementing the interface and an object of that anonymous class".
How does the object store this information? Well, you could invent some super cool new way to store this information. The Java Language designers decided that an anonymous class would be good enough - for the time being. But they had the foresight that if someone came along with a new idea to implement it in a more efficient way, this should be easy to integrate into the Java ecosystem (Java compiler and JVM).
So they also decided to create that anonymous class not at compile time but to let the compiler just write the necessary information into the class file. Now the JVM can at runtime decide on what the optimal way to store the information (calling the correct method on the correct object) is.
For example, when a method reference to an instance method is assigned
to a functional interface then the encapsulating object for that
method is used, but what happens in the case of a static method -
those are not associated with any object..
That depends on context. Let say we have a static Utils#trim(String) method that will obviously trim given string.
And now, lest have a List<String> list and lets have some strings in it. We can do something like this:
list.stream().map(Utils::trim).collect(Collectors.toList());
As you can see, in given context, we are using lambda static method reference in order to use every string in list as input argument of Utils::trim method.

Polymorphic function calls in Java?

Is it possible to polymorphically pass a function to an object array in Java?
I'm trying to create an event-based system, and interfaces simply isn't as versatile as I would like it to be.
As a result, I would like to be able to pass any function to the event manager, and have it execute the function on next iteration.
I would like to be able to pass any function to the event manager
Wouldn't we all. Unfortunately, Java doesn't have first-class functions or even function pointers. So we're stuck with interfaces and anonymous classes, until Java 8 at least.
Why not have your event manager execute Runnables, and wrap your method call with one? (This is the approach Swing took.)
public class Foo {
public void doSomething(){
System.out.println("Hello");
}
}
EventQueue.doLater(new Runnable(){
public void run(){
new Foo().doSomething();
}
}
I'm not sure why Interfaces aren't versatile enough for you - you can do anything you like with interfaces, certainly as much as you could do with passing pure functions.
Typically you would just define a single event handler interface:
public interface EventHandler {
public ReturnType handle(ParamType param);
}
Then you could implement that interface with any number of different handler classes. The handler objects can even contain their own state if that is useful.
Anything you define that implements the interface can then be used polymorphically, e.g. stored in an array so that they can be called in response to a specific event..
Java doesn't support first-class functions.
But you can do almost that by using anonymous classes or using EventHandler class.
This is from Java Docs.
The simplest use of EventHandler is to install a listener that calls a method on the target object with no arguments. In the following example we create an ActionListener that invokes the toFront method on an instance of javax.swing.JFrame.
myButton.addActionListener(
(ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));
When myButton is pressed, the statement frame.toFront() will be executed. One could get the same effect, with some additional compile-time type safety, by defining a new implementation of the ActionListener interface and adding an instance of it to the button:
//Equivalent code using an inner class instead of EventHandler.
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.toFront();
}
});

Closure and Callbacks

Is there any other way in java to implement call backs apart from inner classes? What is the difference between callbacks and closures?
Closure is how you build it, callback is how you use it.
A callback can be implemented as a closure (in languages that have them) or an implementation of an interface (in Java, as an anonymous inner class or a regular class).
Callback means that you pass a piece of code to a function, so that the function can call that piece of code later. It is a special kind of parameter.
The piece of code can be a function pointer or a closure or an object with well-known methods, depending on what the language offers.
Both closures and anonymous inner classes (and others) can be used as callbacks. A callback is just some code which is passed as an argument to other code.
A big difference of closures, compared to Java's anonymous inner classes, is that (in imperative languages) a closure can modify the variables of the surrounding scope. Wikipedia gives the following example:
var f, g;
function foo() {
var x = 0;
f = function() { return ++x; };
g = function() { return --x; };
x = 1;
alert('inside foo, call to f(): ' + f()); // "2"
}
foo();
alert('call to g(): ' + g()); // "1"
alert('call to f(): ' + f()); // "2"
A callback is just any executable code that is passed as a parameter to other code. In frequent usage, that executable code is a closure, but it's not necessarily.
The word closure is somewhat abused and many people just use it as a synonym for "anonymous function", but at least according to Wikipedia, that's a misuse of the term. The Wikipedia article explains this better than I can do quickly.
If you need closures in java you could try lambdaj. Here you can see how it allows to define closures through a very straightforward DSL.
I don't think so.
If there is, then it is probably inferior in some way, otherwise anonymous inner classes wouldn't be widely used.
There is no difference.
Closures can be defined as a block of code holding parent context that can be executed with ease.
In fact, the only difference I know between those is the ease of writing. A typical groovy/ruby closure is indeed smaller to write than a Java anonymous class.
However, considering Java framworks like guava and there liberal use of anonymous classes/interfaces, particularly for typical closures use cases like filter (comparing with groovy's implementation), I can say there is absolutely no design difference.
Sadly the only reasonable way is inner/anonymous classes.
You can also do it with reflection, but that usually is slower and harder in maintenance (no syntax highlighting, hard to find references in IDE etc.). An example:
myButton.addActionListener(EventHandler.create(ActionListener.class, handlerObject, "onClick"));
For now anonymous classes are the best way of handling callbacks in Java. However this is likely to change come Java 7 which will implement closures. http://en.wikipedia.org/wiki/Closure_(computer_science)
Here it is two implementations that uses closures and callbacks.
http://www.caglargonul.com/2013/04/05/playing-with-closures-in-java-7/
http://www.caglargonul.com/2013/04/05/java7-callback-implementation/
And here is a better example (can be found here http://www.caglargonul.com/2013/04/10/is-it-really-a-closure-yes-it-is/ ) for understanding what closure is. The key is that
a closure comes with a referencing environment not just a function code.
The best way to implement a closure in Java 7 and below is using an interface. In this example a callback is implemented as closure.
You first declare your interface which will hold your closure.
public interface CallBack {
void m(int e);
}
And lets add a class responsible for holding an array of closures, two public methods for adding and removing closures and a public function which will call the functions inside the closures when an event occurs.
public class CCallBack {
List<CallBack> cbs = new ArrayList<>();
public void registerCallBack(CallBack f){
cbs.add(f);
}
public void removeCallBack(CallBack f){
if(cbs.contains(f)){
cbs.remove(f);
}
}
public void onAction(int i){
for (CallBack callBack : cbs) {
callBack.m(i);
}
}
}
And here is the magical part. See the referencing environment in action.
public class CallBackTester {
CCallBack cb = new CCallBack();
#Test
public void test_callback(){
CallBack cb1 = new CallBack() {
int x = 1;
#Override
public void m(int e) {
if(e==1){
System.out.println("You register this callback " + x + " time/times");
x++;
}
}
};
cb.registerCallBack(cb1);
cb.registerCallBack(cb1);
cb.registerCallBack(cb1);
cb.removeCallBack(cb1);
cb.onAction(1);
}
}
Above when we declare cb1 we are adding a referencing environment which consists of the variable x. When we call the function inside this closure we are incrementing this variable by one. If it was a normal function, x would have been declared as 1 when we call the function. BUT IT IS NOT A NORMAL FUNCTION. IT IS A CLOSURE. So x is not declared every time we call the function in the closure. As you can see from the output every time we call it, x is incrementing.
You register this callback 1 time/times
You register this callback 2 time/times

Categories

Resources