在Java中调用new时,它是创建构造函数的副本还是类的副本?

在Java中调用new时,它是创建构造函数的副本还是类的副本?,java,class,object,Java,Class,Object,我目前正在做一个Java任务,出于某种原因,它可以工作——但在我看来,它不应该!我有一个主要的方法,通过调用创建三个新按钮 panel.add(new ButtonApp()); ButtonApp是在ButtonApp类中定义的构造函数 在课程开始时,我声明了一个变量,如下所示: public int clicks = 0; 此变量的目的是跟踪用户单击其特定按钮的次数。每次单击后都会调用clicks++ 现在,在我看来,每次单击按钮时,clicks变量应该递增,因此,如果单击左按钮,它应该

我目前正在做一个Java任务,出于某种原因,它可以工作——但在我看来,它不应该!我有一个主要的方法,通过调用创建三个新按钮

panel.add(new ButtonApp());
ButtonApp是在ButtonApp类中定义的构造函数

在课程开始时,我声明了一个变量,如下所示:

public int clicks = 0;
此变量的目的是跟踪用户单击其特定按钮的次数。每次单击后都会调用clicks++

现在,在我看来,每次单击按钮时,clicks变量应该递增,因此,如果单击左按钮,它应该也递增中间和右按钮

因此,在简短的psuedocode中,我的基本内容是:

public class ButtonApp() {
    public int clicks =0;

    public static void main(String[] args) {
        //create JPanel/Frame etc etc
        panel.add(new ButtonApp());
        panel.add(new ButtonApp());
        panel.add(new ButtonApp());
    }

    public ButtonApp(){
        //creates a new button
        this.actionListener(this);
    }

    public void update(){
        clicks++;
    }

    public void actionPerformed (ActionEvent event){
        update();
    }
}
我不是总是在这里增加一个
点击
变量吗?

new()创建类数据的实例——即任何成员变量。代码不重复。在您的例子中,每个类都有自己的“clicks”成员变量


如果您已将
单击
声明为
静态
,则它将是一个“类变量”,属于类本身而不是其实例,然后将只有一个副本。但是,您没有将其声明为静态,因此每个实例(即new()创建的每个“东西”)都有自己的副本。

对于您创建的ButtonApp的3个不同对象,将有3个click变量

panel.add(new ButtonApp());
panel.add(new ButtonApp());
panel.add(new ButtonApp());
如果您想计算总点击次数,忽略哪个按钮点击,只需使
点击
变量
静态

当前,每个对象都有一个不同的
click
变量,但如果将其设置为静态,则每个加载的类都会是相同的

另请参见

我不是总是在这里增加一个变量吗

不,您正在处理实例变量。使用
new

如果将代码更改为:

public static int clicks =0;
实际上,只有一个变量会被多次更改(静态字段属于类,实例字段属于实例)

参考资料:


(全部来自该部分)

每个
按钮都有自己的
点击
变量。如果有三个按钮,则有三次
单击
,并且给定的
单击
仅在按下按钮时递增

如果需要一个
单击
变量,可以将其设置为类变量,而不是实例变量。这是通过
static
关键字完成的:

private static int clicks = 0;
不过,一般来说,最好避免使用静态成员。一种更复杂但更灵活的方法是在所有要链接的按钮之间共享一个计数器对象。您可以创建自己的,但这是一种自然适应,如果您要从UI线程外部访问此状态,则可以提供线程安全性

class ButtonApp {

  private final AtomicInteger clicks;

  ButtonApp(AtomicInteger clicks) { this.clicks = clicks; }

  void update() {
    clicks.incrementAndGet();
  }

  ...

}

您创建了
ButtonApp
类的三个实例,因此可以分别递增这三个属性

您可能会感到困惑,因为您在同一个类中嵌入了
main
方法,并且您认为您正在增加与
main()
相关的实例的
clicks
属性

请记住,
main
static
,这意味着没有与
main
相关的类实例。尝试从
main
访问
单击
,您将看到一个错误

panel.add(new ButtonApp());
将通过调用zero-arg/default构造函数来创建
ButtonApp
类的新实例


对于每个新实例,您将拥有一组新的成员,包括
单击
,因此每次都为零。您的代码没有重复,但您将拥有该类的不同实例,以及它们自己的数据集。

我认为您应该更新标题,使其至少与内部内容相关。您的伪代码表明您正在向应用程序添加侦听器。而不是按钮本身。