方法中的内部类不能访问方法中的局部变量的 【真正原因】

本文探讨了Java中内部类无法直接访问方法局部变量的原因,指出只有当局部变量被声明为final时,内部类才能访问。通过分析字节码和示例代码,展示了内部类如何通过复制final变量的值来保持一致性,并强调了final变量在内部类与局部变量交互中的关键角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package question6;

import java.lang.reflect.Field;

/*
 * 方法中的内部类能不能访问方法中的局部变量,为什么?
 */
public class NoFinalFieldCnnotUsedInner
{
	public static void main(String[] args)
	{
		Outer outer = new Outer();
		SuperInner inner = outer.outer();
		inner.inner();
	}
}
/* 定义一个局部内部类的上层接口,用以允许返回局部内部类实例 */
interface SuperInner
{
	void inner();
}
/* 定义一个外部类,包括一个outer方法,用以返回局部内部类实例 */
class Outer
{
	int y = 0;
	//out方法将返回inner实例
	SuperInner outer()
	{
		//假设我们这里x可以被inner访问,那么outer函数返回之后
		//x已经被销毁,inner对象就无法访问x
		
		//换句话说就是Inner对象的生存周期超出了x的边界,而能保证
		//生存周期一致的情况只有inner对象自己的成员,所以通过在
		//inner里边复制一个x来保存这个局部变量x的值以达到目的
		//就像val$x一样
		
		//但这种办法有个致命点,如果在inner里对val$x进行赋值操作
		//外边的x并不会被改变,所以为了保证两个对象的一致性,该变量
		//x以及其复制变量val$x必须为终态的,也就是final,不能再次
		//赋值
		
		//反编译inner可以证明以上结论,在字节码里
//		question6.Outer$1Inner(question6.Outer, java.lang.String)
		//这是构造方法,传outer不奇怪,内部类都需要外部类的引用指针
		//这个String字符串就值得思考了
		
		//4 getfield val$y 
		//在inner方法中可以看到这个字节码,是val$y 而不是y
		int x = 4;
		final String y = new String("asd");
		class Inner implements SuperInner
		{
//			int val$x = 4;
			public void inner()
			{
				try
				{
					//这里通过反射,可以发现证明此y非彼y,因为我们并没有
					//在inner里定义val$y变量,而我们却可以拿得到,没异常
					//而我们改的是val$y的值为qqq,下边的syso(y)居然会输出
					//qqq,结论可以证实
					
					//通过代码也可以看出来,这个val$y肯定是private的,并且
					//他也是final的
					Field field = getClass().getDeclaredField("val$y");
					field.setAccessible(true);
					System.out.println(field.get(Inner.this));
					field.set(Inner.this, "qqq");
                }
                catch (Exception e)
                {
	                e.printStackTrace();
                }
//				System.out.println(x);本行编译报错,提示局部内部类访问必须是终态的
				System.out.println(y);//输出y的值
			}
		}
		//当inner实例被返回时,x将被销毁
		return new Inner();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值