博客
关于我
Java 内部类及其原理
阅读量:424 次
发布时间:2019-03-06

本文共 1246 字,大约阅读时间需要 4 分钟。

Java中实现内部类

 

内部类相信大家都用过很多次了,就不说它是怎么用的了。

内部类

1.成员内部类

 

需要注意的是, 当成员内部类拥有和外部类同名的成员变量或这方法时, 默认情况下访问的是内部类的成员, 如要访问外部类的同名成员, 需要使用以下形式:

外部类.this.成员变量 外部类.this.成员方法

内部类是依附外部类而存在的, 也就是说要创建成员内部类的对象,前提是创建一个外部类的对象,创建成员内部类的方式如下:

new Main().new Inner();

成员内部类可以拥有private访问权限、protected访问权限、public访问权限、默认访问权限。如用private修饰,则只能在外部类的内部访问。

2.局部内部类

局部内部类是定义在一个方法或作用域中的类,它的访问权限仅限于方法内或作用域内。

 

局部内部类也可以返回,像这样:

 

3.匿名内部类

匿名内部类应该是我们平常使用最多的了,如下面创建线程:

 

匿名内部类在编译的时候有系统自动起名:Main$1

匿名内部类是没有构造器的类,大部分用于继承其他类或实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写

4.静态内部类

静态内部类也是定义在另一个类里面的类,只不过在类前加上了static。静态内部类是不需要依赖于外部类的,与静态成员变量类似。

 

外部创建该静态类时可以如下创建:

Main.Inner mi = new Main Inner();

内部类实现原理

内部类为什么能够访问外部类的成员?

定义内部类如下:

 

使用javap命令进行反编译。

编译后得到Main.class Main$Inner.class两个文件,反编译Main$Inner.class文件如下:

 

可以看到,内部类其实拥有外部类的一个引用,在构造函数中将外部类的引用传递进来。

匿名内部类为什么只能访问局部的final变量?

其实可以这样想,当方法执行完毕后,局部变量的生命周期就结束了,而局部内部类对象的生命周期可能还没有结束,那么在局部内部类中访问局部变量就不可能了,所以将局部变量改为final,改变其生命周期。

编写代码如下:

 

这段代码编译为Main.class Main$1.class两个文件,反编译Main$1.class文件如下:

 

可以看到,java将编译时已经确定的值直接复制,进行替换,将无法确定的值放到了内部类的常量池中,并在构造函数中将其从常量池取出到字段中。

可以看出,java将局部变量m直接进行复制,所以其并不是原来的值,若在内部类中将m更改,局部变量的m值不会变,就会出现数据不一致,所以java就将其限制为final,使其不能进行更改,这样数据不一致的问题就解决了。

匿名内部类为什么访问外部类成员字段不用final?

上面说了,final关键字是为了解决数据不一致的问题,因为内部类中存有外部类的引用,所有对外部类中字段的修改都会真实的反映到外部类实例本身,所以不需要用final来修饰。

转载地址:http://eshuz.baihongyu.com/

你可能感兴趣的文章
Linux下的系统监控与性能调优:从入门到精通
查看>>
LiveGBS user/save 逻辑缺陷漏洞复现(CNVD-2023-72138)
查看>>
localhost:5000在MacOS V12(蒙特利)中不可用
查看>>
mac mysql 进程_Mac平台下启动MySQL到完全终止MySQL----终端八步走
查看>>
Mac OS 12.0.1 如何安装柯美287打印机驱动,刷卡打印
查看>>
MangoDB4.0版本的安装与配置
查看>>
Manjaro 24.1 “Xahea” 发布!具有 KDE Plasma 6.1.5、GNOME 46 和最新的内核增强功能
查看>>
mapping文件目录生成修改
查看>>
MapReduce程序依赖的jar包
查看>>
mariadb multi-source replication(mariadb多主复制)
查看>>
MaterialForm对tab页进行隐藏
查看>>
Member var and Static var.
查看>>
memcached高速缓存学习笔记001---memcached介绍和安装以及基本使用
查看>>
memcached高速缓存学习笔记003---利用JAVA程序操作memcached crud操作
查看>>
Memcached:Node.js 高性能缓存解决方案
查看>>
memcache、redis原理对比
查看>>
memset初始化高维数组为-1/0
查看>>
Metasploit CGI网关接口渗透测试实战
查看>>
Metasploit Web服务器渗透测试实战
查看>>
Moment.js常见用法总结
查看>>