Using final 1-element array for anonymous inner class

I stumbled upon this trick to get the value from an anonymous inner class of a variable declared in the outer class. It works, but it feels like a dirty hack:

private int showDialog() { final int[] myValue = new int[1]; JPanel panel = new JPanel(); final JDialog dialog = new JDialog(mainWindow, "Hit the button", true); dialog.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); JButton button = new JButton("Hit me!"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { myValue[0] = 42; dialog.setVisible(false); } }); panel.add(button); dialog.add(panel); dialog.pack(); dialog.setVisible(true); return myValue[0]; } 

(Yes, I understand that this example can be replaced with a simple JOptionPane , but my actual dialogs are much more complicated.) The internal function insists that all the variables it interacts with are final , but I cannot declare myValue final because an internal function must assign a value to it. Declaring this problem as an array with 1 element turns around this problem, but it looks like it might be Bad Thing TM in some way. I wonder if.) This is a common practice or b) there are serious problems that may arise as a result of this.

+6
source share
4 answers

If the code is legible, what would it be, I would not say that it is so terrible.

An alternative is to call JButton in a class that has showDialog (which is allowed). The function can set the instance variable to be returned. But this seems less legible to me, so I would prefer your method.

If you are not creating a deeply hierarchical user interface structure, sometimes these little hacks are exactly what you need to do.

If you're interested, you can basically do the same thing with a private inner class:

 private class DialogReturnValue { public int value; } private int showDialog() { final DialogReturnValue myValue = new DialogReturnValue(); JPanel panel = new JPanel(); final JDialog dialog = new JDialog(mainWindow, "Hit the button", true); dialog.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); JButton button = new JButton("Hit me!"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { myValue.value = 42; dialog.setVisible(false); } }); panel.add(button); dialog.add(panel); dialog.pack(); dialog.setVisible(true); return myValue.value; } 

And there is also an ActionListeners look (which may well be the "right").

+3
source

Using AtomicInteger or AtomicReference can make it a little better. This is common practice, but you can make it cleaner by introducing an actual class that implements the ActionListener and exposes the value via getter.

+1
source

It seems dirty. I can’t say how “ordinary” it is, and I don’t know that you risk destroying the world by doing this, but if I need something like that, I would rather bite the bullet and write a fully functional inner class (instead of an anonymous sort) for implementations of ActionListener . Thus, you can influence its nested class fields and, if necessary, call other methods in the enclosing class. Depending on what exactly you are doing, even in order to adhere to this logic, it would be worthwhile just to enter the Dialog window and subclass.

As a bonus, non-anonymous inner classes make debugging a little less painful because you have more informative class identifiers available to you.

0
source

I do not think there is a problem with your code. Sometimes I have to resort to something similar, but I use a special class that wraps the value, and I call the setter in the inner class, but the end result is the same.

 private static class Result{ private Integer value; //getter and setters here } .... final Result result = new Result(); ... new InnerClass(){ void foo(){ result.setValue(42); } } 

The problem is that inner classes can only refer to final variables, since their memory address will not change.

My only advice for you is not to use int[] as the value, but Integer[] so that you can tell the difference between the value 0 and the value that is not set (which will have value = null).

0
source

Source: https://habr.com/ru/post/956604/


All Articles