繁体   English   中英

Java-如何从匿名内部类访问非最终变量?

[英]Java - How am I accessing non final variables from an anonymous inner class?

如下面的代码所示,我正在从ActionListener匿名内部类访问JLabel。 这不会给我带来任何错误,因此如何允许使用此方法,但是如果JLabel位于INSIDE,则在没有final修饰符的情况下不允许使用该方法?

JLabel e = new JLabel("");
        public void myMethod() {

            JButton b = new JButton("ok");
            b.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    e.setSize(200,200);

                }

            });

        }

如果该变量在方法def内,则它是一个局部变量-并且您要实例化一个对象,该对象将在该方法执行后存在,并且该局部变量的生命周期已经结束(位于该方法的堆栈框架中)在方法返回时销毁)。 为了使它完全起作用需要一些编译器魔术,并且通常将其称为闭包 ,即使其当前在Java中的实现如此la脚。 编译器实际上将合成一个类,该类实现ActionListener并具有一个实例变量,该本地变量的值将被复制到该实例变量。

这是Java特有的限制,由于线程安全问题,您只能在final var上关闭。 这里的故事说,Java开发人员的直觉是,本地var始终是线程安全的-它不能在方法执行过程中进行更改(该方法未明确进行任何更改),可以如果没有非Datavars,等等。如果您可以关闭非最终变量,则可能会违反该规则,因为该关闭可以与当前执行的方法并行执行并更改该变量。 这将导致一些非常违反直觉的行为。

但是,有一个(有些la脚)解决方法:

public void myMethod() {
    final JLabel[] e = {new JLabel("")};
    JButton b = new JButton("ok");
    b.addActionListener(new ActionListener() {
       @Override public void actionPerformed(ActionEvent arg0) {
         e[0].setSize(200,200);
    }});
}

e现在是一个单元素数组,它驻留在堆上,并且不会被方法的stackframe破坏。 您还可以凭直觉看到现在绝对不是线程安全的,并且侦听器可以轻松地将e[0]的值更改为完全不同的值,并且此处显示的方法将观察到该更改,而无需使用显式的突变代码。它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM