终于明白为什么要加 final 关键字了!

点击上方“Java后端技术”,选择“置顶或者星标”

你关注的就是我关心的!

640?wx_fmt=jpeg

来源:www.jianshu.com/p/acc8d9a67d0c

在开发过程中,由于习惯的原因,我们可能对某种编程语言的一些特性习以为常,特别是只用一种语言作为日常开发的情况。但是当你使用超过一种语言进行开发的时候就会发现,虽然都是高级语言,但是它们之间很多特性都是不太相同的。

现象描述

在  Java 8 之前,匿名内部类在使用外部成员的时候,会报错并提示 “Cannot refer to a non-final variable arg inside an inner class defined in a different method”

640?wx_fmt=jpeg

但是在 Java 8 之后,类似场景却没有再提示了:

640?wx_fmt=jpeg

难道是此类变量可以随便改动了吗?当然不是,当你试图修改这些变量的时候,仍然会提示错误:

640?wx_fmt=jpeg

可以看到,当试图修改基本数据类型的变量时,编译器的警告变成了 “Varible 'num' is accessed from within inner class, need to be final or effectively final”,很遗憾,仍然不能修改。相比之下,Kotlin 是没有这个限制的:

640?wx_fmt=jpeg

原因分析

从表面上当然看不出什么原因,看看编译器做了什么工作吧!运行 javac 命令后生成了几个 .class 文件:

640?wx_fmt=jpeg

不难推断,这个 TestInnerClass$1.class 就是匿名内部类编译后的文件,看看它反编译后是什么内容:

640?wx_fmt=png

原来,匿名也会被当作普通的类处理,只不过编译器生成它构造方法的时候,除了将外部类的引用传递了过来,还将基本数据类型的变量复制了一份过来,并把引用数据类型的变量引用也传递了过来。因此,基本数据类型的变量当然不能修改了,不然就会跟外部的变量产生不一致,这样的话变量的传递也就变得毫无意义了。

情景对比

但是为什么对于 Kotlin 来说可以在匿名内部类中直接修改基本数据类型的值呢?查看 Kotlin 编译后反编译回来的内容:

640?wx_fmt=png

可以发现,当需要传递基本数据类型的变量时,Kotlin 编译器会将这些数据进行包装,从而由值传递变为引用传递,这样内部的修改当然就不会影响到外部了。

验证一下,当变量不进行传递时,Kotlin 编译器是怎么处理的:

640?wx_fmt=png

哈哈,并没有多此一举,点个赞!

热门内容:

1、这可能是史上最详细的 IDEA 中使用 Debug 教程!

2、《历史文章分类导读列表!精选优秀博文都在这里了!》

3、看完这篇还不清楚Netty的内存管理,那我就哭了!

4、Spring中的18个注解,你会几个?

5、祖传代码,轻则伤筋动骨,重则一命呜呼

6、整理了一些 IDEA 中比较骚的技巧,发现第一个就没用过!

7、Google 为什么把几十亿行代码放在一个库

8、Java代码乱象!

9、漫画:互联网人的十二时辰,程序员最惨!

10、Spring 常犯的十大错误,这坑你踩过吗?

640?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值