博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【语法拾零】方法内部类所访问的局部变量为什么必须是final的?
阅读量:6156 次
发布时间:2019-06-21

本文共 1955 字,大约阅读时间需要 6 分钟。

hot3.png

final局部变量也可称为局部常量,赋值以后不再改变。

Java内部类是位于类内部的类,方法内部类即位于类方法内部的类。

比如,Inner是Outer的foo()方法内部类:

public class Outer {	public Other foo() {		final int a = 123;		final String str = "hello";		final Other other = new Other();		final class Inner extends Other {			@Override			public void bar() {				int a1 = a;				String str1 = str;				Other other1 = other;			}		}				return new Inner();	}		public static void main(String[] args) {		Other other = new Outer().foo();		other.bar();	}}class Other {		public void bar() {}}

Java语言规范中说方法内部类只能访问该方法的final局部变量:

Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.

并且,局部变量需要在内部类定义之前赋值:

Any local variable used but not declared in an inner class must be definitely assigned before the body of the inner class.

之所以这么规定,一个理由是:方法执行结束,方法内的局部变量已经销毁,而方法内部类的对象仍可能存在。比如上例中,other.bar()执行时,foo()内的局部变量已经出栈销毁。

问题是,为什么在bar()中能够访问foo()中本该已经销毁了的final局部变量呢?

利用javap得到Outer$1Inner.class的字节码:

public void bar();  Code:   Stack=1, Locals=4, Args_size=1   0:	bipush	123   2:	istore_1   3:	ldc	#24; //String hello   5:	astore_2   6:	aload_0   7:	getfield	#14; //Field val$other:LOther;   10:	astore_3   11:	return  LineNumberTable:    line 12: 0   line 13: 3   line 14: 6   line 15: 11

在foo()方法中定义的3个final局部变量:a,str和other,在Inner的bar()方法中分别被替换成了字面量和Outer$1Inner.class常量池中的常量。

const #14 = Field	#1.#15;	//  Outer$1Inner.val$other:LOther;const #15 = NameAndType	#7:#8;//  val$other:LOther;const #16 = Method	#3.#17;	//  Other."
":()Vconst #17 = NameAndType #9:#18;// "
":()Vconst #18 = Asciz ()V;const #19 = Asciz LineNumberTable;const #20 = Asciz LocalVariableTable;const #21 = Asciz this;const #22 = Asciz LOuter$1Inner;;const #23 = Asciz bar;const #24 = String #25; // hello

由于final局部变量在内部类定义之前赋了值,且不可变,在编译时即可生成该局部变量的常量副本。

虽然方法局部变量的本体已经销毁,它们的静态副本却保留了下来,供方法内部类的对象在合适的时候调用。也可以理解为,局部变量的生命周期通过副本的形式延长了。

转载于:https://my.oschina.net/adolphin/blog/132774

你可能感兴趣的文章
apache 伪静态 .htaccess
查看>>
unity3d 截屏
查看>>
ASP.NET MVC学习之控制器篇
查看>>
MongoDB ServerStatus返回信息
查看>>
分析jQuery源码时记录的一点感悟
查看>>
Sql日期时间格式转换
查看>>
20个最强的基于浏览器的在线代码编辑器 - OPEN资讯
查看>>
Tesseract——OCR图像识别 入门篇
查看>>
《Java程序性能优化》之设计优化
查看>>
Android源代码下载方法具体解释
查看>>
虚拟机 搭建LVS + DR + keepalived 高可用负载均衡
查看>>
maven 发布到仓库
查看>>
Android实现简单短信发送器
查看>>
Linux命令执行顺序— ||和&&和; 比较
查看>>
第30周一
查看>>
一、Bitmap的recycle问题
查看>>
DHCP Option 60 的理解
查看>>
android中的textview显示汉字不能自动换行的一个解决办法
查看>>
程序局部性原理感悟
查看>>
js中document.write()使用方法
查看>>