我正在尝试使用下面的类在HandlerThread
上进行更新,但我有几个关于变量捕获如何在Java中工作的问题。
[1] 通过引用从封闭范围捕获ret
?
[2] this
引用Runnable
,还是从封闭范围内捕获?
[奖励] StartStream
应该将Runnable
发布到处理程序线程,并且仅在Runnable
完成后返回。下面的代码会按预期工作吗?
public class Stream extends HandlerThread {
Handler handler = null;
Stream() {
super("Stream");
handler = new Handler(getLooper());
start();
}
private int _startStream() { // Start some repeating update
return 1;
}
public int StartStream() {
int ret = -1;
handler.post(new Runnable(){
@Override public void run() {
synchronized(this) {
ret = _startStream(); // [1]
this.notify(); // [2]
}
}
});
synchronized(this) {
while(ret == -1) {
try {
this.wait();
}
catch (InterruptedException e){}
}
}
return ret;
}
}
答案 0 :(得分:3)
内部类具有对外部类的隐式引用。
要在匿名内部类中使用ret
,它应该是最终的。局部变量不能引用为非final的原因是因为本地类实例在方法返回后可以保留在内存中。它还取决于java version。仍然应该“有效地最终”或将其移动到成员变量。
this
指的是Runnable,你应该使用Stream.this
来封闭一个。
答案 1 :(得分:1)
ret
是一个局部变量,因此需要有效最终。这意味着,如果ret
在初始化之后被分配给另一个值,编译器会抱怨。因此[1]导致编译器错误。
这是因为Java语言架构师希望防止局部变量(在方法中声明的变量)从声明它的方法以外的地方更改。
有关封闭方法中变量捕获的更多信息:
this
确实引用了Runnable
实例。但是,您可以使用Stream.this
来引用封闭的Stream
实例。