从我们声明内部 class 的方法 local inner class 访问局部变量
Accessing local variables from method local inner class in which we declare the inner class
我正在学习 Java,我正在学习的教程说 Java 不允许从方法 m2 直接访问变量 k(下例中 m1() 的局部变量) () 因为它们是在相同的方法 m1() 中创建的,并且我会在编译时遇到错误(除非 k 被声明为 final)。他们说的原因是局部变量(k)是在方法调用期间创建的,方法执行完成后销毁,但是对象(o)是在实例化对象时创建的,并且在方法执行后仍然不能销毁。所以教程说,如果你在方法 m2 执行后调用方法 m2() 或对象 o(我不知道这是怎么可能的),变量 k 将被破坏并且不可用。所以教程声称 Java 不允许这样的声明。 (不对的地方欢迎指正)
但是当我编译这个程序时工作正常。我错过了什么吗?我知道从我的解释角度来看这有点复杂,所以如果我的问题很清楚,请随时问我是否不清楚。
在此先感谢您的帮助。
class innerclass_ex8
{
int x = 10;
static int y = 20;
public void m1()
{
int k = 30;
final int z = 50;
class inner {
public void m2()
{
System.out.println(x);
System.out.println(y);
System.out.println(k);
System.out.println(z);
}
}
inner o = new inner();
o.m2();
}
public static void main(String[] args)
{
innerclass_ex8 g = new innerclass_ex8();
g.m1();
}
}
首先,您的程序可以编译并正常运行,因为您使用的是 Java8。如果使用 Java7 或更低版本,它甚至无法编译。
原因和你说的一样。但我会尝试多解释一下。考虑以下代码:
public void m1() {
int k = 30;
class inner {
public void m2() {
System.out.println(k);
}
}
inner o = new inner();
k = 42; // <= Note the reassignment here.
o.m2();
}
方法调用 o.m2()
应该打印什么? “30”还是“42”?两种输出都可以合理地争论。在声明和定义方法时,变量 k
的值为 30。在调用方法时,变量 k
的值为 42。
为防止出现此类歧义,编译器不允许对在此类内部 类(本地和匿名)中使用的变量进行赋值。所以一定是final
.
在 Java 8 中,这有点放松。 Java 8引入了effectively final的概念。声明和初始化但未再次分配的变量被视为有效的最终变量。并且编译器允许该代码而不声明变量 final
.
事实上,您在尝试编译上述代码时也会在 Java 8 中遇到编译器错误。
你所说的关于方法内部变量的概念是正确的。如果使用 Java 1.7 或更低版本进行编译,则会抛出编译错误。我猜你正在使用 java 1.8。有一个概念叫 final 变量和有效的 final 变量。在 java 1.8 中,如果分配了方法变量值并且没有再次更改,则它可以执行此代码而不会引发编译时间
错误。
我正在学习 Java,我正在学习的教程说 Java 不允许从方法 m2 直接访问变量 k(下例中 m1() 的局部变量) () 因为它们是在相同的方法 m1() 中创建的,并且我会在编译时遇到错误(除非 k 被声明为 final)。他们说的原因是局部变量(k)是在方法调用期间创建的,方法执行完成后销毁,但是对象(o)是在实例化对象时创建的,并且在方法执行后仍然不能销毁。所以教程说,如果你在方法 m2 执行后调用方法 m2() 或对象 o(我不知道这是怎么可能的),变量 k 将被破坏并且不可用。所以教程声称 Java 不允许这样的声明。 (不对的地方欢迎指正)
但是当我编译这个程序时工作正常。我错过了什么吗?我知道从我的解释角度来看这有点复杂,所以如果我的问题很清楚,请随时问我是否不清楚。
在此先感谢您的帮助。
class innerclass_ex8
{
int x = 10;
static int y = 20;
public void m1()
{
int k = 30;
final int z = 50;
class inner {
public void m2()
{
System.out.println(x);
System.out.println(y);
System.out.println(k);
System.out.println(z);
}
}
inner o = new inner();
o.m2();
}
public static void main(String[] args)
{
innerclass_ex8 g = new innerclass_ex8();
g.m1();
}
}
首先,您的程序可以编译并正常运行,因为您使用的是 Java8。如果使用 Java7 或更低版本,它甚至无法编译。
原因和你说的一样。但我会尝试多解释一下。考虑以下代码:
public void m1() {
int k = 30;
class inner {
public void m2() {
System.out.println(k);
}
}
inner o = new inner();
k = 42; // <= Note the reassignment here.
o.m2();
}
方法调用 o.m2()
应该打印什么? “30”还是“42”?两种输出都可以合理地争论。在声明和定义方法时,变量 k
的值为 30。在调用方法时,变量 k
的值为 42。
为防止出现此类歧义,编译器不允许对在此类内部 类(本地和匿名)中使用的变量进行赋值。所以一定是final
.
在 Java 8 中,这有点放松。 Java 8引入了effectively final的概念。声明和初始化但未再次分配的变量被视为有效的最终变量。并且编译器允许该代码而不声明变量 final
.
事实上,您在尝试编译上述代码时也会在 Java 8 中遇到编译器错误。
你所说的关于方法内部变量的概念是正确的。如果使用 Java 1.7 或更低版本进行编译,则会抛出编译错误。我猜你正在使用 java 1.8。有一个概念叫 final 变量和有效的 final 变量。在 java 1.8 中,如果分配了方法变量值并且没有再次更改,则它可以执行此代码而不会引发编译时间 错误。