0

我一直在尝试学习和弄乱代码。我遇到了一些我没想到会发生的事情。我在 MainApp 类中有一个 JLabel,我创建了一个通过 JLabel 传递的 ActionListener (HelloListener)。按下按钮时,actionPerformed 方法应将 JLabel 更新为“Hello again!”。确实如此,但为什么会这样让我感到困惑。

但是,我认为我必须退回新的 JLabel?当我把HelloListener传给JLabel的时候,那JLabel不就是传完之后HelloListener类的属性吗?所以当它更新时,它只会更新 HelloListener 中的那个,然后我必须返回它?

为什么当我在 HelloListener 中更新 JLabel 时,它也会在 MainApp 类中更新?

这是代码:

public class MainApp extends JFrame {

    public static void main(String[] args) {

        new MainApp();

    }

    public MainApp() {

        setLayout(new GridLayout (2,1));

        setSize(200,200);

        JLabel jl = new JLabel("Hello!");
        add(jl);

        JButton jb = new JButton("Click me!");
        jb.addActionListener(new HelloListener(jl));
        add(jb);

        setVisible(true);

    }

}

public class HelloListener implements ActionListener {

    JLabel jl;

    public HelloListener(JLabel jl) {
        this.jl = jl;
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        jl.setText("Hello again!");
    }

}
4

3 回答 3

3

当我把HelloListener传给JLabel的时候,那JLabel不就是传完之后HelloListener类的属性吗?所以当它更新时,它只会更新 HelloListener 中的那个,然后我必须返回它?

这就是你的理解崩溃的地方。当您“传递 JLabel”时,您传递的是对 JLabel 的引用(实际上是按值传递引用,一旦您了解当前问题,就应该查找它,因为它对 Java 非常重要)。底层对象实例仍然存在于它之前所做的任何地方。因此JLabel jlHelloListener实例中的 只是对 gui 中显示的同一实际 JLabel 实例的引用。

这是 Java(和许多编程语言)如何工作的基础。如果你这样做

Dog d = new Dog();

然后传递d给一个方法

walk(d);

看起来walk

public void walk(Dog dog) {
   dog.setLastWalkTime(now());
   dog.attachLeash(); 
}

dog在方法和d调用范围内,都指向同一个 Dog 实例。因此,当您设置 lastWalkTime 时,底层实例就会被修改。如果在walk您查看之后d,您会看到lastWalkTime您在方法中设置的值。

于 2012-04-10T12:29:47.477 回答
1

当一个函数将一个对象作为参数时,它被传递一个对该对象的引用。在您的代码中,两者MainAppHelloListener引用了同一个JLabel实例。

actionPerformed()被调用时,监听器修改实例的属性。由于JFrame可以访问同一个实例,它会检测到更改并更新 GUI。

于 2012-04-10T12:31:21.937 回答
0

您为什么希望返回新的 JLabel?(然后呢?删除旧的,添加新的,让您的窗口再次进行布局?)您传递给侦听器的 JLabel 实例用作对您的 JLabel 的引用,这就是它的美妙之处 -您正在修改现有实例。

于 2012-04-10T12:30:31.577 回答