Java无法引用非final变量。

3
以下代码仍然报错:

Cannot refer to a non-final variable textBoxPassword inside an inner class defined in a different method Login.java /ChurchWebLogin/src/com/gwt/churchweb/churchweblogin/client line 61

不能在不同方法中定义的内部类中引用非 final 变量 textBoxPassword。
package com.gwt.churchweb.churchweblogin.client;

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.user.client.Window;

public class Login extends Composite {

    public Login() {

        VerticalPanel verticalPanel = new VerticalPanel();
        initWidget(verticalPanel);
        verticalPanel.setSize("329px", "186px");

        Label lblNewLabel = new Label("Sign into your account");
        lblNewLabel.setStyleName("gwt-Login-SigninLabel");
        verticalPanel.add(lblNewLabel);

        FlexTable flexTable = new FlexTable();
        verticalPanel.add(flexTable);
        flexTable.setWidth("308px");

        Label lblNewLabel_1 = new Label("Username:");
        lblNewLabel_1.setStyleName("gwt-Label-Login");
        flexTable.setWidget(0, 0, lblNewLabel_1);
        lblNewLabel_1.setWidth("72px");

        TextBox textboxUsername = new TextBox();
        textboxUsername.setStyleName("gwt-LoginTextBox");
        flexTable.setWidget(0, 1, textboxUsername);
        textboxUsername.setWidth("204px");

        Label lblNewLabel_2 = new Label("Password:");
        lblNewLabel_2.setStyleName("gwt-Label-Login");
        flexTable.setWidget(1, 0, lblNewLabel_2);
        lblNewLabel_2.setWidth("66px");

        TextBox textBoxPassword = new TextBox();
        textBoxPassword.setStyleName("gwt-LoginTextBox");
        flexTable.setWidget(1, 1, textBoxPassword);
        textBoxPassword.setWidth("204px");
        flexTable.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_LEFT);
        flexTable.getCellFormatter().setHorizontalAlignment(1, 0, HasHorizontalAlignment.ALIGN_LEFT);

        CheckBox chckbxRememberMeOn = new CheckBox("Remember me on this computer");
        chckbxRememberMeOn.setStyleName("gwt-Checkbox-Login");
        flexTable.setWidget(2, 1, chckbxRememberMeOn);

        Button btnSignIn = new Button("Sign In");
        btnSignIn.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (textboxUsername.getText().length() == 0
                        || textBoxPassword.getText().length() == 0) {
                        Window.alert("Username or password is empty."); 
                    }
            }
        });

        btnSignIn.setStyleName("gwt-Login-SigninButton");
        flexTable.setWidget(3, 1, btnSignIn);



    }


}

除了链接外,“接受”是感谢那些帮助你的人的一种方式。点击帖子旁边的上箭头是另一种方式。这假设评论是有用的... - Tony Ennis
3个回答

6
final TextBox textboxUsername = new TextBox();

and

final TextBox textBoxPassword = new TextBox();

应该修复它。

Java要求从内部类引用变量时必须是final变量(我想是出于并发管理的原因)。


7
我一直认为这与匿名类在JVM中的编译和执行方式有关,就好像如果在执行匿名函数时无法确定变量的实际值,因为它在执行过程中没有动态检索,而是在先前的步骤中进行了检索。但这只是我的猜测。 - Jack
不仅仅是匿名类,而是任何内部类。 - Jason S
2
从内部类访问非 final 字段是完全合法的,否则我的 90% 代码都无法编译 ;) 问题出现在类是匿名的并且在方法内声明的情况下。 - Jack
啊!你说得对,我不知道为什么我一直在想是普通内部类。 - Jason S
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - smwikipedia

4

如果在内部类中使用局部变量,则必须声明其为final。你应该这样写:

final TextBox textBoxPassword = new TextBox();

2

匿名类实例应该能够访问周围作用域的局部变量和参数。但是,一个实例可能会超出它所在的方法的生命周期(由于将实例引用存储在字段中),并尝试在方法返回后访问不再存在的局部变量和参数。

因为Java不能允许这种非法访问,否则很可能会导致虚拟机崩溃,它只允许匿名类实例访问被声明为final的局部变量和参数。当在匿名类实例中遇到final局部变量/参数名称时,编译器会执行以下两个操作之一:

  • 如果变量的类型是基本类型(例如int或double),编译器将其名称替换为变量的只读值。
  • 如果变量的类型是引用类型(例如String),编译器会在类文件中引入一个合成变量(制造的变量)和存储局部变量/参数引用的代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接