java 监听器中的变量_关于java:变量应该是最终的内部监听器

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:

Cannot refer to a non-final variable inside an inner class defined in a different method

Why are only final variables accessible in anonymous class?

在搜索中,谷歌在寻找这个问题的答案,但找不到任何答案。

我有以下代码:

MyClass variable = new MyClass();

Button b = new Button();

b.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e){

System.out.println("You clicked the button");

variable.doSomething();

}

});

编译器返回:

local variable variable is accessed from within inner class; needs to

be declared final

为什么variable必须是最终的技术原因是什么?

stackoverflow.com/questions/3910324/…、stackoverflow.com/questions/1299837/…等。

谢谢你的链接。没有解释为什么编译器是这样设计的。为什么内部类不具有对outclasses的引用,并在需要时访问变量,而不是在第一次实例化时具有引用?

@盖塔:如果变量是一个成员,你会得到一个点。但它是本地的。您不能依赖它定义的堆栈框架,而Java中没有这样的东西作为变量的引用。所以,如果你想使用它,你几乎必须复制一份。

这是因为您使用的是匿名内部类。编译器会为您创建类。它称之为您的外部类,并添加了$和数字,例如$、$2等。

类具有对自动初始化的外部类的引用,因此其实例可以使用外部类的方法和字段。

但是你的班级是匿名的。它是在方法内部定义的,并且可以使用在此匿名类之前定义的内部变量。问题是"它怎么能做到?"实际上,您不能引用"运行方法的实例"来访问其变量。答案是从匿名内部类引用的所有方法变量都被复制到匿名内部类。因此,变量必须是最终的:否则,某人可以从外部类更改其值,而这些更改在内部类中是不可见的。

这是因为内部类只在触发事件时执行代码。如果变量没有声明为final,那么在variable中引用的MyClass对象可以更改,并且如果需要MyClass对象,内部类将不知道应该引用哪个对象。

因此,它应该声明为最终的,这样引用就永远不会改变。

想象一下,如果没有最后一个关键字:

variable引用MyClass对象和hashCode(): 12345对象。创建了内部类,内部类中的variable使用hashCode(): 12345引用MyClass对象。

variable改为现在引用MyClass对象和hashCode(): abcde对象。内部类中的variable仍然引用MyClass对象和hashCode(): 12345对象。

当事件触发时,Java如何从这里运行代码?使用哪个MyClass对象?

现在使用最后一个关键字:

variable引用MyClass对象和hashCode(): 12345对象。创建了内部类,内部类中的variable使用hashCode(): 12345引用MyClass对象。

由于最后一个关键字,无法更改引用。

当事件触发时,Java总是知道要调用哪个EDCOX1 0对象。没问题。

所以编译器不够聪明,不知道它正在外部类的某个地方设置?

我认为这个答案不正确。"最终"要求适用于所有变量,而不仅仅是引用变量。

@如果是正确的话。原语也会出现同样的问题。线程缓存变量,包括基元和引用。

同样的问题。如果原始变量在内部类之外被更改,那么它将不会反映在内部类中。因此,应宣布为最终决定。

内部类可以引用外部类,并使用该类访问适当的variable。

是的,盖达。这是一种确保它们始终正确引用同一对象的实践

@getah:您访问的是局部变量,而不是成员。没有什么能保证当事件处理程序最终运行时,变量甚至会存在,除非将其设置为final。Java的闭包基本上是通过复制它们需要的变量来实现的,这不会提供从其他函数访问它们的假象,除非变量不能改变。

@Corsika上述问题中提到的问题涉及(方法)局部变量。这个答案解决了一个完全不同的问题,并且对于嵌套类来说,类的字段必须是最终的,才可以访问它们,这一点完全没有必要。

@乔森:这个答案解决了被问到的问题。Java的"闭包"是通过构造一个匿名类并将有用的最终局部变量复制到其中来实现的。它们工作的原因是因为变量不会在不破坏Java规则的情况下发生变化,所以不用担心保持两个副本同步。

BTW.我是唯一一个感觉到Java用户正在打电话的人吗?似乎他们总是选择"解决方案",这意味着对他们来说工作最少,即使这是一个相对糟糕的解决方案…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java监听器是一种特殊的对象,用于监视特定事件并在事件发生时执行代码。如果您想在监听器使用外部变量,可以将这些变量作为参数传递给监听器的构造函数或设置方法,并在需要时访问它们。 例如,假设您有一个名为`count`的整数变量,并且您希望在每次单击按钮时增加它。您可以创建一个监听器来监视按钮单击事件,并在事件发生时增加`count`变量的值。以下是一个示例: ``` public class MyButtonListener implements ActionListener { private int count; public MyButtonListener(int count) { this.count = count; } @Override public void actionPerformed(ActionEvent e) { count++; System.out.println("Button clicked " + count + " times."); } } ``` 在上面的示例,`MyButtonListener`类实现了`ActionListener`接口,并具有一个`count`成员变量。构造函数接受`count`变量的初始值,并将其存储在`count`成员变量。`actionPerformed`方法在每次按钮单击时被调用,并增加`count`变量的值。在这个例子,我们将`count`变量的值打印到控制台,但您可以根据需要执行其他操作。 要使用`MyButtonListener`监听器,您可以创建一个新的`MyButtonListener`对象,并将`count`变量的值传递给它的构造函数,如下所示: ``` int count = 0; JButton myButton = new JButton("Click me!"); myButton.addActionListener(new MyButtonListener(count)); ``` 在上面的示例,我们首先创建一个整数变量`count`并将其初始化为0。然后,我们创建一个新的`JButton`对象,并将一个新的`MyButtonListener`对象作为`addActionListener`方法的参数传递。我们将`count`变量的值作为参数传递给`MyButtonListener`构造函数,以便在监听器使用它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值