1

How do I code a function like this one from lambda:

jButton.addActionListener(ae -> callAnyMethod());

because I am creating a library and would like to implement such a pattern on my own. Before Java 8 and lambda was released how would someone made such a pattern ? like what I am trying to approach is following:

I am trying to set a placeholder into the actionPerformed method of my CustomButton ActionListener and call a method like followed :

CustomButton.CustomButtonListener(placeholder method (); ) 

and the user needs just to create a method and write it inside the bricks ... For example the method named def() :

CustomButton.CustomButtonListener(def());

and def will be passed automatically to the actionPerformed method of my CustomButtonListener and will be fired on button click

Edit:

well that is the code I've came up with so far:

the ActionListener which is stored in my CustomButton class as a method:

public void CustomButtonListener(Object object){

        addActionListener(new ActionListener(){

@Override
        public void actionPerformed(ActionEvent e) {



          // how to call the method stored in the Object "object" here? and actually run it?



            }
    });

and the code snippet from the button:

CustomButton button = new CustomButton();

button.CustomButtonListener(def());





public void def(){

    String a = "lambda!";

            System.out.print("a");



}
SmartCodeNoBugs
  • 51
  • 1
  • 10
  • 6
    By using the existing lambda capabilities in Java? I don't think I understand your question. Can you post what code you have so far and what happens when you run it and what you expected to happen instead? – Robert Jun 27 '17 at 22:30
  • 4
    Are you suggesting that code is not pure Java? Why not? – shmosel Jun 27 '17 at 22:31
  • 1
    `Lambda expressions` where introduced in `Java 8`, you can use them if you can use a version `>7`. – Zabuzard Jun 27 '17 at 22:34
  • 1
    Possible duplicate of [How do I define a method which takes a lambda as a parameter in Java 8?](https://stackoverflow.com/questions/13604703/how-do-i-define-a-method-which-takes-a-lambda-as-a-parameter-in-java-8) – Chris Jun 27 '17 at 22:35
  • As reaction to your edit. You can implement such stuff just by using classes and interfaces. Just create a class that implements the ActionListener interface and the corresponding method. You can make this shorter by using `anonymous classes`. You then create an instance of this object and pass it to the `addActionListener` method. More or less Javas Lambdas do exactly the same (however they have an improved performance). – Zabuzard Jun 27 '17 at 22:39
  • could you pls provide a short example of your implementation just to follow up Zabuza – SmartCodeNoBugs Jun 27 '17 at 22:41
  • Of course, I will convert it to an answer. – Zabuzard Jun 27 '17 at 22:43
  • 3
    @SmartCodeNoBugs Why don't you just look at the documentation and source code of ActionListener, ActionEvent and JButton? And read documentation about lambdas? https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html – JB Nizet Jun 27 '17 at 22:46
  • @JBNizet I don't want to use lambda as I want to learn it the hard way oldschool. In my opinion that's the way to really learn stuff in depth. Don't take it as it is ... ask and break it down into its components to really learn what things are about. – SmartCodeNoBugs Jun 27 '17 at 22:50
  • 3
    JButton, ActionListener and ActionEvent exist, as they are in Java 8, since Java 2. Nothing has changed. Lambdas are just a new way to create an instance of an interface. – JB Nizet Jun 27 '17 at 22:53
  • @SmartCodeNoBugs If you are asking "How do I create the lambda language feature using java" Then the answer is you can't. In order to create a language feature for Java, you need to work on the compiler, and maybe the JVM, and then what you have isn't Java anymore, and likely requires an indepth knowledge of C, JVM internals, and compiler basics. If your question is "how was this accomplished prior to Java 8" It's by the use of anonymous inner classes, but they are not the same as lambda's! – Ryan Leach Jun 28 '17 at 00:56
  • @RyanTheLeach but how would I implement an anonymous inner class into my code I've shown in my post and build an approach like it was made before lambda was introduced I still don't get it how to actually implement this stuff ... – SmartCodeNoBugs Jun 28 '17 at 00:58
  • @SmartCodeNoBugs The other answers show pretty good examples. if you have specific questions that confuse you, I'd suggest commenting on each of them. – Ryan Leach Jun 28 '17 at 01:05
  • Are you trying to create a Lambda like class to fit that interface? Or are you trying to create a class that can accept a Lambda like class as a parameter? – Ryan Leach Jun 28 '17 at 01:06
  • @RyanTheLeach I am trying to set a placeholder into the actionPerformed method of my CustomButton ActionListener and call a method like followed CustomButton.CustomButtonListener(placeholder method (); ) and the user needs just to create a method and write it inside the bricks ... For example the method named def() : CustomButton.CustomButtonListener(def();) and def will be passed automatically to the actionPerformed method of my CustomButtonListener and will be fired on button click that's all I want – SmartCodeNoBugs Jun 28 '17 at 01:10
  • I've sent an edit request to reword your question for you, to be more clear, and avoid the "pure" keyword that was throwing everyone off. Can you make sure that it still accurately reflects your question if/when it gets accepted? – Ryan Leach Jun 28 '17 at 01:29
  • @RyanTheLeach I've edit my question, is it now better ? removed the "pure" keyword as well – SmartCodeNoBugs Jun 28 '17 at 01:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/147767/discussion-between-ryan-the-leach-and-smartcodenobugs). – Ryan Leach Jun 28 '17 at 01:47
  • @SmartCodeNoBugs If an user answered your question please also **accept** his answer ([Accepting Answers: How does it work?](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)). If not than please specify what remains unanswered, this is a really crucial part of StackOverflow, thank you very much. – Zabuzard Jul 27 '17 at 12:00

3 Answers3

3

If I did not misunderstood your question, your syntax is already correct.

public static void main() {
    ...
    jButton.addActionListener(e -> myListener());
    ...
}
...
public void myListener(){
    dosomething();
}

which is the shorthand for this:

public static void main() {
    ...
    MyListener myListener = new MyListener();
    jButton.addActionListener(myListener);
    ...
}

public class MyListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        dosomething();
    }
}

For more information, you can refer to this.

For more detailed explantion you can also refer to this, under the Lambda Type Inference section.

keith ang
  • 115
  • 10
2

Lambda expressions were introduced in Java 8. If you're using an earlier Java version, you can implement the same pattern using classes and interfaces. Just create a class that implements the ActionListener interface and the corresponding method. You can make this shorter by using anonymous classes. You then create an instance of this class and pass it to the addActionListener method. More or less, lambdas do exactly the same (however, they may have an improved performance).

Here is an example:

public static void main() {
    ...
    MyListener myListener = new MyListener();
    jButton.addActionListener(myListener);
    ...
}

public class MyListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Triggered!");
    }
}

And with anonymous classes:

public static void main() {
    ...
    jButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Triggered!");
        }
    });
    ...
}
shmosel
  • 49,289
  • 6
  • 73
  • 138
Zabuzard
  • 25,064
  • 8
  • 58
  • 82
  • thank you for the quick explanation ... but unfortunately I still don't get it. How do I come up with the lambda like pattern like this: jButton.addActionListener(ae -> callAnyMethod()); from your provided code ? – SmartCodeNoBugs Jun 27 '17 at 22:55
  • 1
    Below `Java 8` you can not use Lambda expressions at all because Java does not have this language feature. You can not create such a short expression and need to use implementing classes (as it was originaly intended by the language designer). However Lambda expressions are equivalent to the classes-style, however much shorter to write. – Zabuzard Jun 27 '17 at 22:57
  • The shortest thing I can imagine without lambda is using anonymous `classes` as shown above, or one line shorter without saving it in a variable: `jButton.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {System.out.println("Triggered!");}});` – Zabuzard Jun 27 '17 at 22:58
  • hm thank you but what I really want is: jButton.addCustomListener(callAnyMethod()); that my CustomListener class is a library and the user simply needs to set the CustomListener as above and the callAnyMethod could be a method the user creates itself and only pass it just like lambda does for example: public void passParameter(){ // do something } and now we call this method simply with one line: jButton.addCustomListener(passParameter()); – SmartCodeNoBugs Jun 27 '17 at 23:03
  • @SmartCodeNoBugs - This is precisely why lambdas were invented, so the code looks like this (almost). It's called `functional programming`. You can't use directly`passParameter()`, it will execute the method. – Guillaume F. Jun 27 '17 at 23:07
  • @GuillaumeF. Yes and I want to rebuild the function lambda provides in pure written Java code implemented on my own, maybe that's a bit to much for me for now :/ – SmartCodeNoBugs Jun 27 '17 at 23:08
  • @SmartCodeNoBugs The 'pure way' is in the two answers you got. There is another way called "Reflection", but it's even more advanced, and not really a good practice for a library unless you are a very talented architect. – Guillaume F. Jun 27 '17 at 23:10
  • 1
    You got the answer then complained that it wasn't like lambdas, after saying explicitly that you wanted to avoid the lambda idiom. You should choose one or the other because it won't go both ways at once. And you got a suggestion to read up on lambdas in the Tutorials. Did you do that? The way to substitute any given method as you asked is to provide that method in an implementation of the interface required by the method argument. That's old-school Java. (New-school Java is still "pure" so that was a bad choice of terminology.) – Lew Bloch Jun 27 '17 at 23:56
  • If you want the user to implement the method than just accept an `interface` that contains the method. That is exactly what interfaces are for. The method `jButton.addActionListener` wants an object of the interface `ActionListener` and the only method it contains is `actionPerformed`. Just accept an `ActionListener` object from the user and pass it to `jButton.addActionListener`. – Zabuzard Jun 28 '17 at 00:30
1

You have to identify which Interface your listener uses and declare an anonymous Class.

Lets say that jButton.addActionListener(...) waits for a ActionListener :

jButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        callAnyMethod();
    }
});

Lambdas, which were implemented in Java 8 natively, are another way to access methods and Functional Interfaces in an easy and readable way. The compiler detects automatically what it should use and calls it.


I do not know your project, but if you can afford it, learning how to use Lambdas (and Streams) will greatly increase your productivity, make your code simpler, more readable, and less bug-prone.

Guillaume F.
  • 5,905
  • 2
  • 31
  • 59
  • [`addActionListener()`](https://docs.oracle.com/javase/8/docs/api/javax/swing/AbstractButton.html#addActionListener-java.awt.event.ActionListener-) takes a parameter of type [`ActionListener`](https://docs.oracle.com/javase/8/docs/api/java/awt/event/ActionListener.html), not `Runnable`. – Andreas Jun 27 '17 at 22:47
  • 1
    You don't have to declare an anonymous class to do that, you can use a named subclass of `ActionListener` if you choose. And the technique works for methods that take an extendable class, not just interface arguments. – Lew Bloch Jun 27 '17 at 23:59