Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我的对象会看到构造函数中没有给它的变量?_Java_Variables_Constructor_Visibility - Fatal编程技术网

Java 为什么我的对象会看到构造函数中没有给它的变量?

Java 为什么我的对象会看到构造函数中没有给它的变量?,java,variables,constructor,visibility,Java,Variables,Constructor,Visibility,我有以下代码。这是“正确的”,我不理解: private static void updateGUI(final int i, final JLabel label) { SwingUtilities.invokeLater( new Runnable() { public void run() { label.setText("You have " + i + " seconds.");

我有以下代码。这是“正确的”,我不理解:

private static void updateGUI(final int i, final JLabel label) {
    SwingUtilities.invokeLater( 
        new Runnable() {
            public void run() {
                label.setText("You have " + i + " seconds.");
            }
        }
    );
}
我创建Runnable类的一个新实例,然后在此实例的
run
方法中使用变量
label
I
。它是有效的,但我不明白它为什么有效。为什么所考虑的对象会看到这些变量的值

根据我的理解,代码应该是这样的(而且是错误的):

因此,我会将
I
标签
变量提供给构造函数,以便对象可以访问它们


顺便说一下,在
updateGUI
中,我在
I
标签之前使用
final
。我想我使用了
final
,因为编译器需要它。但是我不明白为什么。

编译器为您完成这项工作(因为您不能在匿名类中使用构造函数)。这背后的基本原理是,
标签
位于内部类的可视区域内。您可以访问对象的字段,也可以创建非匿名的内部类来访问最终参数和局部变量。

因为可以看到外部类的所有变量。
第二个示例的问题是,Runnable接口的实现者应该有一个没有参数的构造函数。

final
封闭方法中声明的变量可以由该方法中的匿名内部类访问。如果将参数设置为非最终参数,则会看到编译器发出抱怨

不能在匿名内部类中声明构造函数。人们有时通过编写初始化程序块来解决这个问题

new Runnable() {
  { /* this code is executed */ }

  public void run() {
    // ...
  }
};

我认为不能访问非最终变量的理由是,如果创建匿名内部类对象,然后更改非最终变量,那么匿名内部类是否应该使用更新的值?当函数终止执行并且变量被销毁时,它如何管理这种情况?如果它只能使用最终变量,那么语义是明确的:它将获取最终变量值的快照

之所以可以这样做是因为final关键字。这是一个解释原因的链接

实际上,理由是updateGUI方法可能在可运行对象被销毁之前终止。事实上,最终变量的值作为额外的隐藏参数传递给内部类构造函数,并由内部类存储在隐藏(最终)属性中。如果您使用
javap
@Stephen查看字节码,您可以看到这一点,真不错。谢谢你的提示。相关问题:
new Runnable() {
  { /* this code is executed */ }

  public void run() {
    // ...
  }
};