Java 将“this”作为方法参数传递-澄清

Java 将“this”作为方法参数传递-澄清,java,swing,methods,this,actionlistener,Java,Swing,Methods,This,Actionlistener,在完成了我的第一套Java课程后,我目前正在学习Java Swing课程。在本课中,我们将研究我们一直在研究的不同组件、按钮、工具栏等之间的通信。问题是,这是作为addActionListener方法的方法参数传递的。这是可行的,但是,我不完全理解它在做什么。我对此做了一些研究,发现this关键字最常用的用法是在具有相同名称变量的构造函数中。我找不到一个适合我的例子。通过查看下面的代码,我将解释我理解的部分代码 import java.awt.FlowLayout; Implements Flo

在完成了我的第一套Java课程后,我目前正在学习Java Swing课程。在本课中,我们将研究我们一直在研究的不同组件、按钮、工具栏等之间的通信。问题是,这是作为addActionListener方法的方法参数传递的。这是可行的,但是,我不完全理解它在做什么。我对此做了一些研究,发现this关键字最常用的用法是在具有相同名称变量的构造函数中。我找不到一个适合我的例子。通过查看下面的代码,我将解释我理解的部分代码

import java.awt.FlowLayout; Implements FlowLayout class
import java.awt.event.ActionEvent; //Imports ActionEvent Class
import java.awt.event.ActionListener; //Imports ActionListener Interface
import javax.swing.JButton; //Imports JButton class
import javax.swing.JPanel; //Imports JPanel class


public class Toolbar extends JPanel implements ActionListener {
    // ^ Inherits JPanel & Implements ActionListener Interface

    private JButton helloButton; //Creating variable of JButton type
    private JButton goodbyeButton; //Creating variable of JButton type


    public Toolbar() { //Constructor

        helloButton = new JButton("Hello"); //Creates new JButton
        goodbyeButton = new JButton("Goodbye"); //Creates new JButton

        helloButton.addActionListener(this); //Question 1
        goodbyeButton.addActionListener(this); //Question 1

        setLayout(new FlowLayout(FlowLayout.LEFT)); //Sets Layout Type to Left


        add(helloButton); //Adds button to FlowLayout (Layout Manager) Interface
        add(goodbyeButton); //Adds button to FlowLayout (Layout Manager) Interface

    }

    public void setTextPanel(TextPanel textPanel) {
        //No Usage Yet!
    }

    public void actionPerformed(ActionEvent arg0) { //Unimplemented Method from ActionListener
        System.out.println("A button was clicked"); //Prints after button is clicked.

    }

}
问题1:正如您所看到的,在创建了两个JButton之后,我们添加了一个addActionListener方法,以查看是否已单击该按钮。如果已单击它,则它将执行在actionPerformed中键入的、从ActionListener接口实现的任何代码。在前面的课程中,我们有一种不同的方法使按钮响应单击。它做了同样的事情,但看起来是这样的:

btn.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent arg0) {

        textPanel.appendText("Hello\n");

        }


    });
在本例中,我们没有打印到控制台以测试actionListener是否工作,而是将文本从自定义组件附加到文本区域。在本文正上方的代码中,我们使用的是一个匿名类

所以。。。问题是,当它作为addActionListener中的方法参数传递时,它到底在做什么?我知道它正在打印一个被点击到控制台的按钮,但我不理解这是怎么做的,以发送按钮被点击到actionPerformed的逻辑

这就是应用程序的外观:

这是正在运行的应用程序,按钮在单击后已打印到控制台。我想这可能会让你更好地了解我在做什么。我希望有人能对此有所了解,并解释这在这种情况下是如何工作的。谢谢大家!

通过实现ActionListener,然后将其传递给addActionListener方法,您要求通过调用actionPerformed方法来通知执行的任何操作

或者,更简单地说,你给按钮你的电话号码,并要求它打电话给你,每当发生什么事

在前面的课程中,您说明了应该发生什么-打印此文本或向textPanel添加一些文本。要做到这一点,你需要在飞行中制作一个ActionListener。现在您自己实现了ActionListener,您可以请求回调,而不是动态创建一个侦听器。

swing组件的addActionListener方法采用ActionListener类型的参数。实现ActionListener的类包含指定当有人与swing组件交互时应执行的操作的代码

当您将其传递给addActionListener方法时,您正在传递对正在实例化的当前对象的引用。事实上,正在实例化的当前对象也是ActionListener,因为它实现了ActionListener,因此可以传递给addActionListener方法

当您在GUI中与JButton交互时,将调用Toolbar类的actionPerformed方法,因为它是您注册JButton的ActionListener。

这只是Toolbar类的一个实例。它在实例方法中用于表示当前实例。本质上,您可以想象您的类有另一个名为this的私有成员变量,它指向工具栏对象

由于Toolbar实现了ActionListener,您正在将新实例化的Toolbar对象指定为按钮的侦听器,这意味着单击按钮时将调用Toolbar.actionPerformed方法。

这表示类的当前实例

工具栏类实现ActionListener接口,这意味着它提供actionPerformed方法的实现

因此,helloButton.addActionListenerthis;如果尝试从类声明中删除实现ActionListener,代码将无法编译

这样一来,工具栏实例可以被视为ActionListener对象,并可以传递给button.addActionListener

使用时

btn.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent event) {
        }
}
您可以动态创建ActionListener接口的新实现。这种实现称为匿名


这两种解决方案都是有效的。如果actionPerformed中的代码无法从其他地方使用,则首选匿名解决方案。

假设所有导入都在那里,并且大写字母正确,则这两个示例也可以执行相同的操作:

public static void main(String args[]){
    myFrame frame = new myFrame();
    myFrame.addActionListener(new myListener);
}

public myFrame extends JFrame{
    public myFrame(){
        super("myFrame");
    }
}

public myListener implements ActionListener{
    public void ActionPerformed(ActionEvent e){
        //Do Stuff
    }
}

拥有ActionListener的优点是,如果您想将方法上的修饰符设置为私有,那么它可以更直接地访问字段和方法。 但是,如果您想避免处理多个b的if/else if异常
我建议您使用单独的ActionListener并提供一种方法来更改需要更改的内容,或者查看匿名类和lambda表达式。

通常使用面向对象的编码,在您正在编码的类中扮演对象的角色是值得的。如果你那样做,这意味着我

因为Java是通过引用传递的,所以这是一个指向我的箭头

public class Foo implements ActionListener {
      public void actionPerformed(ActionEvent e) {
           // do something useful with e
      }
}
这里我们写了一个类Foo。因为我们已经说过它实现了ActionListener,所以它必须有一个actionPerformed方法。任何东西都可以称之为:

ActionListener listener = new Foo(...);
ActionEvent event = ...;
foo.actionPerformed(event);
我们可以创建一个Foo并将其提供给生成事件的对象:

ActionListener listener = new Foo(...);
button.addListener(listener);
如果我们扮演这个对象,你可以把最后一行想象成“嘿”按钮!无论何时发生动作,都要告诉听众

现在,如果我们想让听者自己控制谁在说什么呢?嘿,巴顿,无论什么时候有行动都告诉我

public class Foo implements ActionListener {

      public attachToButton(JButton button) {
           button.addActionListener(this);
      }

      public void actionPerformed(ActionEvent e) {
           // do something useful with e
      }
}
想象一下按钮的addActionListener代码可能是什么样子可能会有所帮助:

public class JButton {  // not the real JButton code, but it will be similar
    private List<ActionListener> actionListeners = new ArrayList<ActionListener>();

    public void addActionListener(ActionListener a) {
         actionListeners.add(a);
    }

    // called internally when an event happens
    private void onEvent(ActionEvent e) {
        for(ActionListener listener : actionListeners) {
            listener.actionPerformed(e);
        }
    }
}

因此,如果您是名为addActionListenerthis的侦听器,则该列表包含一个指向您的引用,每次发生动作时,按钮都会使用该引用轻拍您的肩膀。

谢谢!你的回答很清楚。
public class JButton {  // not the real JButton code, but it will be similar
    private List<ActionListener> actionListeners = new ArrayList<ActionListener>();

    public void addActionListener(ActionListener a) {
         actionListeners.add(a);
    }

    // called internally when an event happens
    private void onEvent(ActionEvent e) {
        for(ActionListener listener : actionListeners) {
            listener.actionPerformed(e);
        }
    }
}