Java动作澄清

时间:2013-07-11 17:30:22

标签: java

所以,通常,我是C,C ++和C#程序员,我在C#WPF中拥有大部分GUI经验。我被安排在一个使用Java的项目上,我发现我的C#词汇与Java不相符。

我遇到过一个与JButton有关的问题,可能是C#中所谓的“委托”。从example开始,有一些代码:

jbnButton1.addActionListener(new ActionListener()
{
    public void actionPerformed(ActionEvent e) 
    {
        jtfInput.setText("Button 1!");
    }
});

简单地说,这是什么叫做,将函数定义为参数(或作为参数传递)?这也是最佳做法吗?在我正在进行的项目中,Initialize()函数用于按钮,复选框等功能,这使得它成为一个相当不实用的功能。我更喜欢在类级别定义,而不是在Initialize()中。

这将我带到另一个example(顶级代码示例)。使用以下代码行:

    b1.addActionListener(this);
    b3.addActionListener(this);
...
}

public void actionPerformed(ActionEvent e) {
    if ("disable".equals(e.getActionCommand())) {
        b2.setEnabled(false);
        b1.setEnabled(false);
        b3.setEnabled(true);
    } else {
        b2.setEnabled(true);
        b1.setEnabled(true);
        b3.setEnabled(false);
    }
} 

本质上,代码将按钮1,b1和按钮3,b3的动作分配给同一事件处理程序,该处理程序在我喜欢的范围(在按钮初始化之外)定义。有没有办法让它们指向不同的功能?另外,通过调用

.addActionListener(this);

编译器如何在此使用actionPerformed(ActionEvent e)?是预先定义的,表示操作将解析为'actionPerformed(ActionEvent e)'?

3 个答案:

答案 0 :(得分:1)

您给出的第一个示例称为“匿名内部类”。您正在定义ActionListener的匿名子类,重写其actionPerformed方法,实例化它(创建此子类的实例),然后将对该实例的引用传递给方法jbnButton1.addActionListener 。这是目前最接近Java的“封闭”(至少在Java 8之前)。

当动作侦听器很简单时,这是惯用的,但您可以将其重新编码为

class MyListener extends ActionListener
{
    public void actionPerformed(ActionEvent e) 
    {
        jtfInput.setText("Button 1!");
    }
}
...
jbnButton1.addActionListener(new MyListener());

但是您可能需要安排MyListener的构造函数来接受并保存jtfInput引用。内联定义简化了这一点。但是对于更复杂的情况,您可能希望将该类定义为外联。

至于第二个问题:

.addActionListener(this);

出现此类的类必须实现ActionListener接口,因此它必须具有actionPerformed()方法。这就是让框架“知道”调用内容的原因。

答案 1 :(得分:1)

您的第一个示例称为匿名类。它通常用于监听器(如ActionListener s),但只有在您不必删除监听器时才应使用它,因为没有保存引用。

对于问题的第二部分,编译器不知道何时调用actionPerformed。它在ActionListener documentation

中声明
  

当动作事件发生时,将调用该对象的actionPerformed方法。

因此,JButton有责任在发生操作时添加到其中的所有actionPerformed上调用ActionListener

无法让b1b3指向不同的方法。这是一个很好的例子,说明匿名类可以用于更好的设计:

b1.addActionListener(new ActionListener()
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
        b2.setEnabled(false);
        b1.setEnabled(false);
        b3.setEnabled(true);
    }
});

b3.addActionListener(new ActionListener()
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
        b2.setEnabled(true);
        b1.setEnabled(true);
        b3.setEnabled(false);
    }
});

假设b1有标签“禁用”。然后this将不再需要实施ActionListener

答案 2 :(得分:1)

对于您的第二个代码示例:

它知道使用actionperformed(),因为您用来将actionlistener - s添加到按钮的类正在实现接口ActionListener

如果你传递addActionListener方法你自己的类(this),你必须实现actionPerformed方法,它就像anonymous classes一样,因为它是ActionListener

addActionListener方法知道它有一个actionPerformed方法(它必须有一个),所以它会自动调用