Java 作为参数传递的Final
在下面的示例中,它通过将参数Java 作为参数传递的Final,java,parameters,final,Java,Parameters,Final,在下面的示例中,它通过将参数int i设置为final class Miner1 { Miner getMiner(final int i) { return new Miner() { public void perform_work() { System.out.println(i); } }; } interface Miner { v
int i
设置为final
class Miner1
{
Miner getMiner(final int i) {
return new Miner() {
public void perform_work() {
System.out.println(i);
}
};
}
interface Miner { void perform_work(); }
否则,如果没有像前面的示例那样设置为final,它将不会编译。
有人知道为什么吗?即使没有final
,它也应该在范围内,因为大括号尚未闭合
提前感谢。这与范围无关 在Java中,匿名类只能引用那些来自外部作用域的变量,这些变量是
final
从:
在内部类中使用但未声明的任何局部变量、形式参数或异常参数必须声明为final
这与范围无关,而是与范围有关 不能从父类中声明的匿名类访问局部变量,除非该变量是
final
看看上面的其他问题,这就解释了逻辑。Java只允许从方法/构造函数中定义的匿名类引用最终变量/参数。这是为了使代码的行为更加直观。在创建实例时,变量/参数的值通过隐藏构造函数参数传递给匿名类的实例,因此匿名类的实例无法跟踪变量的进一步更改。如果允许访问非最终变量,可以编写以下内容:
int a = 5;
Thread t = new Thread ()
{
@Override
public void run ()
{
System.out.println (a); // This will print 5, rather than 6!
}
};
a = 6;
t.start ();
class MyThread extends Thread
{
int _a;
public MyThread (int a)
{
this._a = a;
}
@Override
public void run ()
{
System.out.println (_a);
}
}
int a = 5;
Thread t = new MyThread (a); // Value `5` is passed
a = 6;
t.start (); // Value `5` passed to the constructor earlier is printed here
并希望打印6
。要理解为什么上面的代码会打印5
,请注意此代码等同于以下代码:
int a = 5;
Thread t = new Thread ()
{
@Override
public void run ()
{
System.out.println (a); // This will print 5, rather than 6!
}
};
a = 6;
t.start ();
class MyThread extends Thread
{
int _a;
public MyThread (int a)
{
this._a = a;
}
@Override
public void run ()
{
System.out.println (_a);
}
}
int a = 5;
Thread t = new MyThread (a); // Value `5` is passed
a = 6;
t.start (); // Value `5` passed to the constructor earlier is printed here
这是因为,在Java中,匿名内部类只能访问最终的局部变量和类的字段。
现在的问题是为什么?
这是因为方法的局部变量(
getMiner
在您的例子中)存在于堆栈上,并且仅在方法的生命周期内存在。局部变量的范围仅限于声明变量的封闭方法。当方法结束时,堆栈帧被吹走,变量为历史。但是,即使在方法完成之后,在其中创建的内部类对象在堆上可能仍然是活动的。例如,如果通过getMiner
获得的匿名内部类Miner
的引用被传递到另一个代码位置并在那里使用,那么由于局部变量已经被放大,对于该对象来说,这将是一种奇怪的情况。这个问题的一个解决方案是匿名内部类对象复制局部变量。但它也不能保证匿名内部类对象将看到该变量的最新值,因为局部变量容易发生更改。但是如果局部变量是final,它确保了变量值在初始化后在任何情况下都不会改变,因此,方法local internal class只需将其复制一份供私人使用,即使原始值已从堆栈中删除,它仍将存在。我本打算回答这个问题,但上面的链接已经很好地涵盖了它:-)+1'd+1@defaultlocale:谢谢您,先生。我一直在寻找那句话,但在错误的部分!非常清楚,谢谢。