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

现象描述

在 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 编译器是怎么处理的:

最新文章

  1. iOS开发:创建真机调试证书及描述文件
  2. mac下tomcat的安装与配置
  3. Oracle(控制用户权限)
  4. PHP对redis操作详解【转】
  5. FPGA的典型应用领域
  6. jQuery ajax - get(),getJSON(),post()方法
  7. 【转】终于干了点正事。。三天用了三个库opencv、emgu、aforge.net[2011.7.30]
  8. 创建组合索引SQL从1个多小时到1S的案例
  9. sql server 数据库附加时程序集错误
  10. javascript常用的107个语句
  11. 深入理解Arrays.sort() (转)
  12. C语言之基本算法37—数组最大值及其位置
  13. angular 按下回车键触发事件
  14. 存图方式---邻接表&邻接矩阵&前向星
  15. Oracle12c(12.1)中性能优化&功能增强之通过参数THREADED_EXECTION使用多线程模型
  16. [No000016F]高并发下线程安全的单例模式(最全最经典)
  17. rabbitmq学习(二):rabbitmq(消息队列)的作用以及rabbitmq之直连交换机
  18. [Python] 中文路径和中文文本文件乱码问题
  19. xe7 控件升级
  20. JS随机数种子

热门文章

  1. 内存回收导致关键业务抖动案例分析-论云原生OS内存QoS保障
  2. 大学四年因为分享了这些软件测试常用软件,我成了别人眼中的(lei)大神(feng)!
  3. 关于有符号数和无符号数的转换 - C/C++
  4. Django(21)migrate报错的解决方案
  5. Scala 中 object、class 与 trait 的区别
  6. nginx 配置 conf stream
  7. 如何实现一个简易版的 Spring - 如何实现 AOP(中)
  8. Runtime PM 处理不当导致的 external abort on non-linefetch 案例分享
  9. 友盟umeng消息推送直接复制就能用(纯干货)
  10. pika详解(五)登录认证及connectionParameters