a can only be final here. Why? How can I reassign a in onClick() method without keeping it as private member? private void f(Button b, final int a){ b.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int b = a*5; } }); } How can I return the 5 * a when it clicked? I mean, private void f(Button b, final int a){ b.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int b = a*5; return b; // but return type is void } }); }
当前回答
访问被限制为局部final变量的原因是,如果所有的局部变量都是可访问的,那么它们首先需要被复制到一个单独的部分,在那里内部类可以访问它们,并且维护可变局部变量的多个副本可能会导致数据不一致。而final变量是不可变的,因此任何数量的拷贝都不会对数据的一致性产生任何影响。
其他回答
要理解这种限制的基本原理,请考虑以下程序:
public class Program {
interface Interface {
public void printInteger();
}
static Interface interfaceInstance = null;
static void initialize(int val) {
class Impl implements Interface {
@Override
public void printInteger() {
System.out.println(val);
}
}
interfaceInstance = new Impl();
}
public static void main(String[] args) {
initialize(12345);
interfaceInstance.printInteger();
}
}
The interfaceInstance remains in memory after the initialize method returns, but the parameter val does not. The JVM can’t access a local variable outside its scope, so Java makes the subsequent call to printInteger work by copying the value of val to an implicit field of the same name within interfaceInstance. The interfaceInstance is said to have captured the value of the local parameter. If the parameter weren’t final (or effectively final) its value could change, becoming out of sync with the captured value, potentially causing unintuitive behavior.
匿名内部类中的方法可以在生成该类的线程终止后调用。在您的示例中,内部类将在事件分派线程上调用,而不是在创建它的线程中调用。因此,变量的作用域是不同的。所以为了保护这样的变量赋值范围问题,你必须声明它们为final。
试试这段代码,
创建数组列表并将值放入其中并返回:
private ArrayList f(Button b, final int a)
{
final ArrayList al = new ArrayList();
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
int b = a*5;
al.add(b);
}
});
return al;
}
Java内部类中的final变量[关于]
内部类只能使用
外部类引用 final局部变量来自范围外的引用类型(例如Object…) 值(原语)(例如int…)类型可以由最终引用类型包装。IntelliJ IDEA可以帮助您将其转换为一个元素数组
当编译器生成一个非静态嵌套(内部类)时-一个新类- <OuterClass>$<InnerClass>.class创建并将有界参数传递给构造函数[堆栈上的局部变量],它类似于闭包[Swift about]
Final变量是不能重新赋值的变量。最终引用变量仍然可以通过修改状态来更改
如果这是可能的,那就奇怪了,因为作为一个程序员,你可以做出这样的东西
//Not possible
private void foo() {
MyClass myClass = new MyClass(); //Case 1: myClass address is 1
int a = 5; //Case 2: a = 5
//just as an example
new Button().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
/*
myClass.something(); //<- what is the address - 1 or 2?
int b = a; //<- what is the value - 5 or 10 ?
//illusion that next changes are visible for Outer class
myClass = new MyClass();
a = 15;
*/
}
});
myClass = new MyClass(); //Case 1: myClass address is 2
int a = 10; //Case 2: a = 10
}
也许这个把戏能给你启发
Boolean var= new anonymousClass(){
private String myVar; //String for example
@Overriden public Boolean method(int i){
//use myVar and i
}
public String setVar(String var){myVar=var; return this;} //Returns self instane
}.setVar("Hello").method(3);
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap