我偶然发现了这个技巧,从匿名内部类中获取一个值,该变量在外部类中声明。它有效,但感觉就像一个肮脏的黑客:
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];
}
(是的,我知道这个例子可以用简单的JOptionPane
替换,但我的实际对话框要复杂得多。)内部函数坚持认为它与之交互的所有变量都是final
,但是我无法将myValue
声明为final,因为内部函数需要为其赋值。将它声明为1元素阵列解决了这个问题,但似乎它可能是某种坏事 TM 。我想知道是否a。)这是常见做法或b。)这可能导致任何严重问题。
答案 0 :(得分:3)
如果代码清晰可辨,我就不会这样做那么糟糕。
另一种方法是让JButton在具有showDialog(允许)的类中调用一个函数。该函数可以设置将返回的实例变量。但这对我来说似乎不太清晰,所以我更喜欢你的方法。
除非你正在制作一个深度分层的UI框架,否则有时这些小黑客就是你应该做的事情。
如果您担心,您可以使用私有内部类基本上做同样的事情:
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;
}
还有ActionListeners可供查看(这可能是“正确的”方法)。
答案 1 :(得分:1)
使用AtomicInteger或AtomicReference可以使小更好。这实际上是一种常见的做法,但您可以通过引入实现ActionListener的实际类并通过getter提供值来使其更清晰。
答案 2 :(得分:0)
看起来很脏。我真的不能说它是多么“普通”,而且我不知道你这样做会冒着破坏世界的风险,但如果我需要这样的东西,我宁愿咬紧牙关写一个完整的内部类(而不是匿名变种)来实现ActionListener
。这样你可以让它影响它的封闭类的字段,并根据需要调用封闭类中的其他方法。根据你正在做的事情,甚至可能值得全押和继承Dialog
以保持这种逻辑。
作为奖励,非匿名内部类使调试变得不那么痛苦,因为您可以使用更多信息类标识符。
答案 3 :(得分:0)
我认为你的代码没有问题。我有时不得不求助于类似的东西,但是我使用了一个包装值的特殊类,我在内部类中调用了一个setter,但最终的结果是相同的。
private static class Result{
private Integer value;
//getter and setters here
}
....
final Result result = new Result();
...
new InnerClass(){
void foo(){
result.setValue(42);
}
}
问题是内部类只能引用最终变量,因为它们的内存地址不会改变。
我唯一的建议是不要使用int[]
作为值而是使用Integer[]
,这样就可以区分值0和未设置的值(这将具有value = null)。