Thinking In Java里面的说法(***正确的说法): 如果定义一个匿名内部类,并且希望它使用一个在其外部定的对象,那么编译器会要求其参数引用是final 的。publicclassTester {

publicstaticvoidmain(String[] args) {

A a =newA();

C c =newC();

c.shoutc(a.shout(5));

}

}

classA {

publicvoidshouta() {

System.out.println("Hello A");

}

publicA shout(finalintarg) {

classBextendsA {

publicvoidshouta() {

System.out.println("Hello B"+ arg);

}

}

returnnewB();

}

}

classC {

voidshoutc(A a) {

a.shouta();

}

}

第5行c.shoutc(a.shout(5)),在a.shout(5)得到返回值后,a的shout()方法栈被清空了,即arg不存在了,而c.shoutc()却又调用了a.shouta()去执行System.out.println("Hello B" + arg)。

再来看Java虚拟机是怎么实现这个诡异的访问的:有人认为这种访问之所以能完成,是因为arg是final的,由于变量的生命周期,事实是这样的吗?方法栈都不存在了,变量即使存在,怎么可能还被访问到?试想下:一个方法能访问另一个方法的定义的final局部变量吗(不通过返回值)?

研究一下这个诡异的访问执行的原理,用反射探测一下局部内部类 。编译器会探测局部内部类中是否有直接使用外部定义变量的情况,如果有访问就会定义一个同类型的变量,然后在构造方法中用外部变量给自己定义的变量赋值,而后局部内部类所使用的变量都是自己定义的变量,所以就可以访问了。见下:classA$1$B

{

A$1$B(A,int);

privatefinalintvar$arg;

privatefinalAthis$0;

}

A$1$B类型的对象会使用自定义的var$arg变量,而不是shout()方法中的final int arg变量,当然就可以访问了。

那么为什么外部变量要是final的呢?即使外部变量不是final,编译器也可以如此处理:自己定义一个同类型的变量,然后在构造方法中赋值就行了。原因就是为了让我们能够挺合逻辑的直接使用外部变量,而且看起来是在始终使用 外部的arg变量(而不是赋值以后的自己的字段)。

考虑出现这种情况:在局部内部类中使用外部变量arg,如果编译器允许arg不是final的,那么就可以对这个变量作变值操作(例如arg++),根据前面的分析,变值操作改变的是var$arg,而外部的变量arg并没有变,仍然是5(var$arg才是6)。因此为了避免这样如此不合逻辑的事情发生:你用了外部变量,又改变了变量的值,但那个变量却没有变化,自然的arg就被强行规定必须是final所修饰的,以确保让两个值永远一样,或所指向的对象永远一样(后者可能更重要)。

还有一点需要注意的是内部类与方法不是同时执行的,比如实现ActionListener,只有当事件发生的时候才会执行,而这时方法已经结束了。

【编辑推荐】

【责任编辑:杨赛 TEL:(010)68476606】

点赞 0

java局部内部类 final_Java的局部内部类以及final类型的参数和变量相关推荐

  1. java final成员变量吗_阳光沙滩博客-为什么Java匿名内部内使用局部变量需要加final?而访问成员变量却不用加final呢?...

    前置知识 内存数据区域(Java内存结构) 在解析这个问题之前,得先有一些前置知识. 比如说,要知道什么是堆,什么是栈,什么是方法区,这数据区域存放什么内容? 可以参考这篇文章: 栈里面存放方法内容 ...

  2. 【Java报错】mapper传入array\collection\list类型的参数时报BindingException:Parameter `` not found(问题复现+3种解决方法)

    1. 问题说明 这里只贴出核心代码: // 查询数据 List<StatisticalInfo> statisticalInfoList = null; // 保存数据 boolean i ...

  3. java继承a mya new c,“内部类” 大总结(Java),内部类总结java

    "内部类" 大总结(Java),内部类总结java (本文整理自很久以前收集的资料(我只是做了排版修改),作者小明,链接地址没有找到,总之感谢,小明) 内部类的位置: 内部类可以作 ...

  4. Java的(((φ(◎ロ◎;)φ))) 实例(成 员)内部类、局部内部类、匿名内部类和静态内部类。

    关于让你晕头的Java类 总结 2.细枝末节 小试牛刀 Biu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~pia! # 梳理一下 # 前言 Java里有各种各样 ...

  5. 内部类(成员内部类+局部内部类+静态内部类+匿名内部类)

    内部类的定义:在java中,允许在一个类的内部定义类,称为内部类,这个内部类所在的类称为外部类.内部类定义在外部内的内部,通常只服务于外部类,对于其他外部是不具备可见性的. 内部类应用场景:1.当某个 ...

  6. 内部类详解————局部内部类

    内部类三连击: <内部类详解----匿名内部类> <内部类详解----局部内部类> <内部类详解----静态嵌套类> 定义 在方法或某个作用域内的内部类,称为局部内 ...

  7. Java编程思想 第十章:内部类

    可以将一个类的定义放在另一个类的定义内部,这就是内部类 内部类远不止如此,它就像是一个外围类:并能与之通信:而且你用内部类写出来的代码更加优雅清晰. 1. 创建内部类 将一个类定义在另一个类的内部,这 ...

  8. Java的知识点14——内部类的概念、内部类的分类

    内部类的概念 一般情况,我们把类定义成独立的单元.有些情况下,我们把一个类放在另一个类的内部定义,称为内部类(innerclasses). 内部类可以使用public.default.protecte ...

  9. java提高篇(八)----详解内部类

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

最新文章

  1. Golang 解决unsupported protocol scheme问题
  2. [LeetCode226]Invert Binary Tree
  3. socket实现进程间通信
  4. 2020年余丙森概率统计强化笔记-第五章 大数定律和中心极限定理 第六章 数理统计
  5. SQLMAP使用笔记
  6. Babelfish (STL)
  7. 语法分析器自动生成工具一览
  8. Linux命令 — 设置或查看网络配置命令ifconfig
  9. js (javascript) 中获取年月日信息
  10. 经验分享:10个简单实用的 jQuery 代码片段
  11. Python异步非阻塞IO多路复用Select/Poll/Epoll使用
  12. react jest测试_如何设置Jest和Enzyme来测试React Native应用
  13. 51单片机-矩阵键盘
  14. 蜂窝移动网络是什么?它和Wi-Fi有什么区别?
  15. 蓄力一纪,可以远矣!十二年的百度地图和他的AI新征程
  16. HTML5汽车赛道飙车游戏,死亡赛道飙车
  17. 机器学习通俗入门-Softmax 求解多类分类问题
  18. 马科维茨投资组合理论(均方模型)学习笔记——基于Matlab(四)
  19. 西门子200Smart加维纶触摸屏程序画面程序案例,项目内容为某制造企业疫苗车间控制系统,报告配液工艺
  20. 苏州电脑数据恢复中心怎么样

热门文章

  1. 我要认真学Git了 - Config
  2. (转)在阿里,我们如何管理代码分支?
  3. 垃圾回收算法优缺点对比
  4. ZooKeeper3.4.5-最基本API开发
  5. 【Lolttery】项目开发日志 (三)维护好一个项目好难
  6. 深入了解tcmalloc(一):windows环境下无缝拦截技术初探
  7. Linux系统文件类型 特殊文件 和 进程间通信机制
  8. git 配置图形比较工具
  9. 万彩录屏服务器不稳定,万彩录屏 云服务器
  10. leetcode 922. 按奇偶排序数组 II(双指针)