java局部内部类 final_Java的局部内部类以及final类型的参数和变量
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类型的参数和变量相关推荐
- java final成员变量吗_阳光沙滩博客-为什么Java匿名内部内使用局部变量需要加final?而访问成员变量却不用加final呢?...
前置知识 内存数据区域(Java内存结构) 在解析这个问题之前,得先有一些前置知识. 比如说,要知道什么是堆,什么是栈,什么是方法区,这数据区域存放什么内容? 可以参考这篇文章: 栈里面存放方法内容 ...
- 【Java报错】mapper传入array\collection\list类型的参数时报BindingException:Parameter `` not found(问题复现+3种解决方法)
1. 问题说明 这里只贴出核心代码: // 查询数据 List<StatisticalInfo> statisticalInfoList = null; // 保存数据 boolean i ...
- java继承a mya new c,“内部类” 大总结(Java),内部类总结java
"内部类" 大总结(Java),内部类总结java (本文整理自很久以前收集的资料(我只是做了排版修改),作者小明,链接地址没有找到,总之感谢,小明) 内部类的位置: 内部类可以作 ...
- Java的(((φ(◎ロ◎;)φ))) 实例(成 员)内部类、局部内部类、匿名内部类和静态内部类。
关于让你晕头的Java类 总结 2.细枝末节 小试牛刀 Biu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~pia! # 梳理一下 # 前言 Java里有各种各样 ...
- 内部类(成员内部类+局部内部类+静态内部类+匿名内部类)
内部类的定义:在java中,允许在一个类的内部定义类,称为内部类,这个内部类所在的类称为外部类.内部类定义在外部内的内部,通常只服务于外部类,对于其他外部是不具备可见性的. 内部类应用场景:1.当某个 ...
- 内部类详解————局部内部类
内部类三连击: <内部类详解----匿名内部类> <内部类详解----局部内部类> <内部类详解----静态嵌套类> 定义 在方法或某个作用域内的内部类,称为局部内 ...
- Java编程思想 第十章:内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类 内部类远不止如此,它就像是一个外围类:并能与之通信:而且你用内部类写出来的代码更加优雅清晰. 1. 创建内部类 将一个类定义在另一个类的内部,这 ...
- Java的知识点14——内部类的概念、内部类的分类
内部类的概念 一般情况,我们把类定义成独立的单元.有些情况下,我们把一个类放在另一个类的内部定义,称为内部类(innerclasses). 内部类可以使用public.default.protecte ...
- java提高篇(八)----详解内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...
最新文章
- Golang 解决unsupported protocol scheme问题
- [LeetCode226]Invert Binary Tree
- socket实现进程间通信
- 2020年余丙森概率统计强化笔记-第五章 大数定律和中心极限定理 第六章 数理统计
- SQLMAP使用笔记
- Babelfish (STL)
- 语法分析器自动生成工具一览
- Linux命令 — 设置或查看网络配置命令ifconfig
- js (javascript) 中获取年月日信息
- 经验分享:10个简单实用的 jQuery 代码片段
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用
- react jest测试_如何设置Jest和Enzyme来测试React Native应用
- 51单片机-矩阵键盘
- 蜂窝移动网络是什么?它和Wi-Fi有什么区别?
- 蓄力一纪,可以远矣!十二年的百度地图和他的AI新征程
- HTML5汽车赛道飙车游戏,死亡赛道飙车
- 机器学习通俗入门-Softmax 求解多类分类问题
- 马科维茨投资组合理论(均方模型)学习笔记——基于Matlab(四)
- 西门子200Smart加维纶触摸屏程序画面程序案例,项目内容为某制造企业疫苗车间控制系统,报告配液工艺
- 苏州电脑数据恢复中心怎么样