阅读本文大概须要 2.8 分钟。
java
来源: www.jianshu.com/p/acc8d9a67d0c程序员
在开发过程当中,因为习惯的缘由,咱们可能对某种编程语言的一些特性习觉得常,特别是只用一种语言做为平常开发的状况。
可是当你使用超过一种语言进行开发的时候就会发现,虽然都是高级语言,可是它们之间不少特性都是不太相同的。
现象描述
在 Java 8 以前,匿名内部类在使用外部成员的时候,会报错并提示
“Cannot refer to a non-final variable arg inside an inner class defined in a different method”:
可是在 Java 8 以后,相似场景却没有再提示了:
难道是此类变量能够随便改动了吗?固然不是,当你试图修改这些变量的时候,仍然会提示错误:
能够看到,当试图修改基本数据类型的变量时,编译器的警告变成了
“Varible 'num' is accessed from within inner class, need to be final or effectively final”,很遗憾,仍然不能修改。相比之下,Kotlin 是没有这个限制的:
缘由分析
从表面上固然看不出什么缘由,看看编译器作了什么工做吧!运行
javac
命令后生成了几个 .class 文件:
不难推断,这个 TestInnerClass$1.class 就是匿名内部类编译后的文件,看看它反编译后是什么内容:
原来,匿名也会被看成普通的类处理,只不过编译器生成它构造方法的时候,除了将外部类的引用传递了过来,还将基本数据类型的变量复制了一份过来,并把引用数据类型的变量引用也传递了过来。所以,基本数据类型的变量固然不能修改了,否则就会跟外部的变量产生不一致,这样的话变量的传递也就变得毫无心义了。
情景对比
可是为何对于 Kotlin 来讲能够在匿名内部类中直接修改基本数据类型的值呢?查看 Kotlin 编译后反编译回来的内容:
能够发现,当须要传递基本数据类型的变量时,Kotlin 编译器会将这些数据进行包装,从而由值传递变为引用传递,这样内部的修改固然就不会影响到外部了。
验证一下,当变量不进行传递时,Kotlin 编译器是怎么处理的:
哈哈,并无画蛇添足,点个赞!
·END·编程
程序员的成长之路微信
路虽远,行则必至编程语言
本文原发于 同名微信公众号「程序员的成长之路」,回复「1024」你懂得,给个赞呗。ide
回复 [ 520 ] 领取程序员最佳学习方式学习
回复 [ 256 ] 查看 Java 程序员成长规划3d
