2

I'm designing a P2P messaging application using Swing, and have been running into serious issues when it comes to organizing my GUI component ActionListeners. Each JButton and JTextField almost always needs its own ActionListener implementation designed, because each component naturally has a different effect on the application than the others. My immediate thought was to just use lambdas to define an actionPerformed() call for each unique component, but this becomes even more problematic, because lambdas cannot be passed any parameters from the caller (as far as I know) since we don't have any constructor to use as a passer. In short, it seems I have to choose between two options:

  1. Create a new class implementing ActionListener for each component requiring unique action logic, cluttering my codebase to a preposterous degree (BUT allowing for parameter passing via said class's constructor/native methods).
  2. Use an actionPerformed() lambda for each component requiring unique action logic, streamlining my codebase while requiring a complete redesign of said logic's details due to the loss of parameter passing.

I would be stunned, however, if this bad choice road is the reality of the situation. Is there an alternative to these poor options? Maybe a programming paradigm I've entirely overlooked?

5
  • 5
    You might benefit of reading and eventually applying some design patterns as solutions. First, you can pass parameters to lambdas, as long as they are final. Here are a list of patterns that comes to mind and might help: Command, Strategy, Observer, Action/Input Map, Mediator and Factory. You can apply all or some it depends on your implementation details, which you left out of your question. Commented Jun 19 at 19:01
  • 5
    Lambdas can reference local variables outside the lambda as long as they're final or effectively final (and are in scope, obviously). An effectively final variable is simply a variable that can be marked final without issue. Lambdas can also reference fields, which don't have to be (effectively) final. When an outside local variable or field is referenced inside a lambda, the lambda implementation captures the object. For instance fields, the captured object is the enclosing this. For static fields, the lambda implementation just queries the field directly (no capturing). Commented Jun 19 at 19:53
  • 1
    Example: String str = "Hi"; Runnable r = () -> System.out.println(str);. The lambda has captured the object referenced by str (i.e., "Hi"). This is essentially the same as passing str to a named class implementation of Runnable via a constructor. Commented Jun 19 at 19:54
  • 1
    @JorgeCampos looks like it's time to check back in with the Gang of Four lol. Thanks for the recommendations! Commented Jun 19 at 21:20
  • @Slaw and this was what I was looking for. Codebase is now far prettier AND more functional, something I hadn't even dared to hope for. Thanks for the help! Commented Jun 19 at 21:22

1 Answer 1

5

There's no problem with using lambdas. Here's an example of adding some behaviour to a menu item:

cutMenuItem.addActionListener( e -> textComponent.cut() );

Notice that the lambda can refer to textComponent from the scope in which the lambda is created. It happens that in this case that component was passed to a method that constructs a menu for it. The thing a lambda can't refer to is a non-final variable, and the compiler will do its best to make variables final for you if you use them in lambdas (they become "effectively final").

You expressed concern with cluttering your code with listener implementations. Lambdas don't prevent you having to define a lot of listeners, but they are a concise way of defining them.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! I feel really dumb for forgetting about the effectively final thing. And the clutter I was worried about was simply the full class definitions, so the lambda concision is exactly what I'm looking for.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.