java final关键字修饰局部变量,Java进阶 ——— 局部内部类访问局部变量为什么必须加final关键字..._十七卷的博客-程序员宅基地

技术标签: java final关键字修饰局部变量  

疑问

在Java中,局部内部类如果调用了方法中的变量,那么该变量必须申明为final类型,如果不申明,则编译就会出错。

这里的内部类指的是方法内部类或匿名内部类,不包含静态内部类和成员内部类

这里通过一个例子类分析

public class InnerClass {

private int defaultAge = 5;

局部变量 age,必须添加final关键字,这里先不加

public void addAge( int age){

//局部内部类

class NewAge{

private int getAge(){

return age + defaultAge;

}

}

NewAge newAge = new NewAge();

System.out.print(newAge.getAge());

}

}

复制代码

强行不加final,编译,则会报错:

Error:(16, 12) 错误: 从内部类中访问本地变量age; 需要被声明为最终类型

分析

原因

1.生命周期不同: 为什么必须局部变量加final关键字呢?因为局部变量直接存储在栈中,当方法执行结束,非final的局部变量就被销毁,而局部内部类对局部变量的引用依然存在,当局部内部类要调用局部变量时,就会出错,出现非法引用。简单来说,就是非final的局部变量的生命周期比局部内部类的生命周期短,是不是直接可以拷贝变量到局部内部类?这样内部类中就可以使用而且不担心生命周期问题呢?也是不可以的,因为直接拷贝又会出现第二个问题,就是数据不同步 2.数据不同步:内部类并不是直接使用传递进来的参数,而是将传递进来的参数通过自己的构造器备份到自己内部,表面看是同一个变量,实际调用的是自己的属性而不是外部类方法的参数,如果在内部类中,修改了这些参数,并不会对外部变量产生影响,仅仅改变局部内部类中备份的参数。但是在外部调用时发现值并没有被修改,这种问题就会很尴尬,造成数据不同步。所以使用final避免数据不同步的问题

原理

那为什么添加final修饰的局部变量,就可以被局部内部类引用呢? 若定义为final,则java编译器则会在内部类NewAge内生成一个外部变量的拷贝,而且可以既可以保证内部类可以引用外部属性,又能保证值的唯一性 也就是拷贝了一个变量的副本,提供给局部内部类,这个副本的生命周期和局部内部类一样长,并且这个副本不可以修改,保证了数据的同步 注意:在Java8 中,被局部内部类引用的局部变量,默认添加final,所以不需要添加final关键词

字节码

如果有兴趣,可以看看编译后的字节码,即.class文件

class InnerClass$1NewAge {

//可以看到,局部内部类中的使用的age,是通过构造函数传递进来,并不是直接引用外部变量。

InnerClass$1NewAge(InnerClass var1, int var2) {

this.this$0 = var1;

this.val$age = var2;

}

private int getAge() {

return this.val$age + InnerClass.access$000(this.this$0);

}

}

复制代码

InnerClass类编译后,在文件夹会出现InnerClass.class和InnerClass$1NewAge.class,这说明外部类的方法 和内部类处于同一级。

结论

局部内部类引用局部变量,不添加final,会出现生命周期不同,导致非法引用问题,而且直接拷贝会出现数据不同步问题,所以使用final,保证了合法引用,而且数据不可修改

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_36155936/article/details/115776688

智能推荐

sftp上传文件_喝着绿茶的猫的博客-程序员宅基地_sftp上传文件

rm删除文件rmdir删除文件夹,但是只能删除空文件夹。因此要使用命令rm folder/* 把文件夹里面的文件先清空, 再rmdir folder。而且还需要是folder里面没有子文件夹的情况。(文件名:folder)put 上传文件利用sftp中将本地文件夹D:\a\folder(内包含子文件夹) ,上传到复制到服务器的/mmm目录下 1、切换到远程目录/mmm : cd /mm

window下Anaconda安装tensorflow、keras_FootMark.run的博客-程序员宅基地

卸载、安装,,,辗转了一天终于装上了tensorflow和keras首先,window下Python2.7不支持tensorflow,Python3.5和3.6都支持以前学习opencv用的是Python2.7(只支持2.7),在没有卸载Python2.7的情况下,又安装了anaconda3-5.0.0在下,conda install tensorflow,回车很简

Google推出Gmailify功能:无需Gmail账户、亦可享受同等服务_weixin_34292402的博客-程序员宅基地

自2015年初以来,Google的Gmail Android应用就允许用户管理非Gmail邮件账户,比如Yahoo或Outlook。现在,该公司更进了一步,并推出了全新的“Gmailify”功能,以便任何人都能够享受到Gmail的垃圾邮件防护、收件箱管理、Google Now集成,而无需变更他们的email地址。也就是说,你将不仅仅能够检查@Yah...

生产环境linux服务器系统安全配置_weixin_33985679的博客-程序员宅基地

第一章 账户安全及权限一、禁用root以外的超级用户1. 检测方法:cat /etc/passwd 查看口令文件,文件格式如下login_name:password:user_ID:group_ID:comment:home_dir:command若user_ID=0,则该用户拥有超级用户的权限。查看此处是否有多个ID=02. 检测命令:cat /etc/pas...

(转)网络工程师笔记(二)_Pitbull2014的博客-程序员宅基地

网络工程师笔记(最后一波)3、路由选择协议网络互联 网络互联通常是交换机和路由器之间的互联 交换机和交换机互联的不足: 1、广播风暴(交换机不支持) 2、网络互联(交换机只能是相同子网的互联) 3、网络安全 在网络添加了路由器,就可以有效防止这三种问题 路由器根据IP地址来区分不同网络,实现网络的互联和隔离。同时它具有隔离广播的作用,把广...

51头文件总结_E_ROAD_BY_U的博客-程序员宅基地

1)“文件包含”处理概念   所谓“文件包含”是指在一个文件内将另外一个文件的内容全部包含进来。因为被包含的文件中的一些定义和命令使用的频率很高,几乎每个程序中都可能要用到,为了提高编程效率,减少编程人员的重得劳动,将这些定义和命令单独组成一个文件,如reg51.h,然后用#include包含进来就可以了,这个就相当于工业上的标准零件,拿来直接用就可以了。2)寄存器地址及位地址声明的原

随便推点

Zstack和vmware的初步印象对比_USTC-lup的博客-程序员宅基地_zstack和vmware

先不说话,直接上截图吧,vmware的:zstack的:读者不知道看出什么名堂没有?把浏览器缩放调到50%,vmware的产品线两页截屏还装不下;zstack虽然也要两屏,但都是块块,大致数了数,Zstack的某个版本涉及到的所有下载条目一共9条,连vmware的1/5都不到。因为有服务器用着vmware,想要用vcenter管管,到官网想下载个东东,看到上面,感觉头都要炸了,不关心时没有去对较,这样比一比,真是吓一跳。也许vmware的产品线拉的很长,所以要这么多条目,但核心的虚拟

教你使用MobaXterm连接VMware虚拟机进行MySQL配置安装——连接SQLyog_玺泺的博客-程序员宅基地_mobaxterm安装mysql

一、在moba连接上VMware虚拟机的情况下,把左下角Follow terminal folder给√上。二、创建新目录,依次输入命令:mkdir /softscd /softs输入完毕后就新建了softs目录,并且已经进入该目录三、然后把我们的配置文件从我们的文件夹里直接用鼠标拖到softs目录下,就是左边空白区域,然后就会看到下方会出现加载的进度条,完成后就是下图的样子,有了两个MySQL开头的文件。四、下面开始安装依赖包等一系列操作,需要依次输..

poj题目分类记录_twinslizzy维的博客-程序员宅基地

http://blog.csdn.net/lyy289065406/article/details/6642573#comments

JAVA实现EXCEL行列号解析(二)——多格解析_howardliuchenxi的博客-程序员宅基地

当然,Excel不仅仅只能实现单格解析,还有如同多格解析的比如A1:B3;实际上是一个一维数组了,解析办法如下:/** * 比如,通过A1:B3返回的是A1,B1,A2,B2,A3,B3 * @param cellstr * @return */ public static ArrayList cellNames(String cellStr) { if(cellStr

CC2530学习笔记(2)—— IO端口基本操作实验(按键控制亮灯)_程序猿来是你的博客-程序员宅基地

https://blog.csdn.net/zzz_xxj/article/details/793483972018年02月22日 17:47:24 ZZZ_XXJ 阅读数:913 标签: ZigBeeCC2530GPIOLEDKEY 更多个人分类: ZigBeeCC2530学习笔记(2)—— IO端口基本操作(按键控制亮灯) 关于CC2530的IO端口基本知识、IO端口有关寄...

Tailwind 真香_hyomei的博客-程序员宅基地_tailwind

一、导入在进入 Tailwindcss 主题之前,我们先来聊聊 css 的发展历程,这将有利于理解 tailwind 存在的意义。CSS 经历了三个阶段:原生阶段:需要什么就写什么。组件化阶段:将相同视觉的UI封装成一个组件,像Bootstrap、Element UI、Antd 都是采用这个做法,比如你需要一个按钮,要多次使用并且样式一致,就可以封装成一个按钮类,之后使用就直接用这个类名就ok了。原子化阶段:其实也是组件化的一种,只不过每个组件都是单一功能的 css 属性。举个例子

推荐文章

热门文章

相关标签