如果一个类有内部类,编译将生成几个字节码文件,规则是怎样呢?

写在前,自己动手丰衣足食,结论只有个人实验支持,没有官方数据支持,欢迎自行查阅文档然后来指正,轻喷,谢谢。

1.普通类包含内部类的样例

public class Test319 {private static class StaticInner{ }//静态内部类private class Inner{}//成员内部类public void outerFunction1(){class PartInner3{}//局部内部类3}public void outerFunction2(){class PartInner1{}//局部内部类1class PartInner2{}//局部内部类2}public Thread thread1 = new Thread(new Runnable() {//匿名内部类1@Overridepublic void run() {}}, "thread1");public Thread thread2 = new Thread(new Runnable() {//匿名内部类2@Overridepublic void run() {}}, "thread2");public Thread thread3 = new Thread(()->{//匿名内部类(使用lambda表达式)},"thread3");
}

2.编译后生成的文件目录

3.小总结

首先,包括外部类在内一共有9个类,而目录中只有8个class文件,可以看出一套规律:全部内部类编译后都会生成字节码文件,但是匿名内部类有个特点
1.成员内部类:外部类名后加一个dollar接内部类名
2.静态内部类:和成员内部类一样(毕竟都是外部类的成员,静态非静态而已)
3.局部内部类:在dollar后比成员内部类多了个数字
4.匿名内部类:dollar后只有一个数字,如果使用lambda表达式创建匿名内部类将不生成class文件,否则会生成
其次,局部内部类和不使用lambda表达式创建的匿名内部类,他们的class文件名都包含数字,数字究竟是什么含义?(在没有查资料的情况下,首先猜测,数字顺序就是内部类声明的顺序)先用两个匿名内部类来进行测试,后面再说局部内部类的问题。

4.关于文件名中数字的测试(匿名内部类)

第一步,为了观察方便给代码做些调整,加入简单的方法体。

public Thread thread1 = new Thread(new Runnable() {//匿名内部类1@Overridepublic void run() {System.out.println("Hello World");}}, "thread1");public Thread thread2 = new Thread(new Runnable() {//匿名内部类2@Overridepublic void run() {int i = 10;i += 1;}}, "thread2");

先声明的进行print操作,后声明的进行int加法计算。通过javap命令对两个字节码进行解释,结果如下:


由上述过程可看出,小数字的进行了print,大数字的进行了int+1,而定义的顺序也就是print操作的在前,int+1操作的在后。
第二步,使用相同手法,在.java文件中调换两个操作的声明顺序,即先声明的进行int+1操作,后声明的进行print操作,得到了相同的结论,具体不再赘述。
通过反复实验,结果一致。但因为没有查阅官方文档,先提出一个我自己的想法:数字顺序是内部类的声明顺序,同时作为区分匿名内部类的依据

5.关于局部内部类

再回过头说局部内部类的问题。匿名内部类没有名字自然需要数字区分,那么如果其他有名字的内部类名称重复怎么办(此情况只能发生于局部内部类)?同样可以先得出一个结论,数字是区分重名局部内部类的依据
但是我发现数字顺序并不是声明顺序……不再赘述实验过程,简单来说在外部类的两个方法里定义名称相同的局部内部类,调换两个方法的声明位置。编译后文件目录如下:

这里看出数字不再是声明顺序,定义了两个局部内部类的方法我是后声明的,数字反而变成了1而不是2。有种被逗了的感觉。秉持着“死也不去查资料先作作看结果”的精神,实验继续……(*其实是我不知道该去看官方的哪个文档,也懒得去找*
新定义和新编译生成的文件目录如下:

public class Test319 {public void outerFunction1(){class PartInner1{}}public void outerFunction2(){class PartInner1{}class PartInner2{}}public void outerFunction3(){class PartInner1{}class PartInner2{}class PartInner3{}}
}


差一点,我就以为数字顺序是内部类所在方法定义的逆序了。还好所做了几组实验,毕竟自己归纳就已经很不科学了,更不能仅从一组实验就得出结论。中间步骤不说了,直接来看最后一组实验:

public class Test319 {public void outerFunction1(){class PartInner1{}}public void outerFunction3(){class PartInner1{}class PartInner2{}class PartInner3{}}public void outerFunction2(){class PartInner1{}class PartInner2{}class PartInner3{}class PartInner4{}class PartInner5{}}public void outerFunction0(){class PartInner1{}class PartInner2{}class PartInner3{}class PartInner4{}}
}


具体的自行细品吧,直接说我的结论:定义内部类个数最多的方法,它里面的内部类生成的class文件,名称里的数字就是最小的。

6.最终总结

大致总结在上面的【3】,再总结一下关于数字的事情。
首先关于为什么会有数字,因为匿名内部类没名字(废话。。。),局部内部类名称可能相同,所以数字用来做不同内部类之间的区分,这也是为什么只有他们两个编译出来的字节码文件,名称中带有数字。
其次关于数字顺序,匿名内部类,数字顺序是声明顺序;局部内部类,定义内部类个数最多的方法,它里面的内部类生成的class文件,名称里的数字就是最小的。
以上是个人实验的结果,未查阅文档,有一定的不可靠性。但是懒得去找和读文档了,欢迎指正。

包含内部类的.java文件编译后生成几个.class文件相关推荐

  1. java源程序是由类定义_无论Java源程序包含几个类的定义,若该源程序文件以A.java命名,编译后生成的都只有一个名为A的字节码文件...

    无论Java源程序包含几个类的定义,若该源程序文件以A.java命名,编译后生成的都只有一个名为A的字节码文件 答:× 小儿头皮静脉输液时如误注入动脉,局部表现为: 答:呈树枝状苍白 人民群众既是历史 ...

  2. STM32 MDK编译后生成的 .map文件深入分析

    .map文件是STM32开发中非常重要的一个文件,在该文件中可以详细的查看单个文件.函数及用户定义的全局变量等的占用RAM和ROM(一般为片内FLASH)的空间大小,通过了解这些信息可以很方便的进行代 ...

  3. java $.class_java文件编译后额外生成的$1.class是怎么一回事

    首先java文件编译生成class文件其基本规则是这样的: 内部类的class文件命名是:主类+$+内部类名 匿名类的class文件命名是:主类+$+(1,2,3....) 但是如果没有使用匿名类,会 ...

  4. java $ class_java文件编译后额外生成的$1.class是怎么一回事

    首先java文件编译生成class文件其基本规则是这样的: 内部类的class文件命名是:主类+$+内部类名 匿名类的class文件命名是:主类+$+(1,2,3....) 但是如果没有使用匿名类,会 ...

  5. JAVA编译成文件的说法_下列关于使用Javac命令编译后生成文件的说法中,正确的是?...

    下列关于使用Javac命令编译后生成文件的说法中,正确的是? 答:编译后生成的文件可以在Java虚拟机中运行\n\n编译后生成的文件为二进制文件\n\n编译后生成文件的后缀名为.class 线性表的链 ...

  6. java编译生成哪些文件_java编译后生成什么文件?生成的文件包括什么?

    在大家编译完java程序的时候,都是会生成一个文件的,作为java新手不清楚java编译后生成什么文件?那么今天我们就给大家讲解一下这方面的内容,大家可以参考下文哦! java文件编译过后会生成一个c ...

  7. Maven在pom文件中添加资源插件后,src/main/resource目录中的文件编译后不拷贝解决方法。

    在pom文件中添加以下资源插件后 <!--添加的资源插件--> <build><resources><resource><directory> ...

  8. java程序编译成exe文件_将java程序编译成独立运行的exe文件

    将java程序编译成独立运行的exe文件 众所周知java的程序可以"一次编译,到处运行",这个特性不错,但是实现这个特性的前提是当前的平台 必须有相应的jvm,而且如果当前平台的 ...

  9. 在Ubuntu终端使用mkdir创建文件夹后Xftp不能上传文件到文件夹中的问题解决方法

    问题描述 在Ubuntu终端上使用mkdir创建文件夹后使用Xftp上传文件失败 原因分析: 权限问题 解决方案: chmod 777 File

最新文章

  1. Scrum中文网-是否需要在Sprint计划会上分完所有任务?
  2. 【PHPExcel】设置打印格式
  3. 【LoadRunner】OSGI性能测试实例
  4. 上次谁说要简历模板来着?来!
  5. echart 饼图设置指引线_EXCEL中把饼图砍一半,美观程度瞬间提升
  6. vue项目 预览照片的插件 v-viewer
  7. linux git中央仓库地址,如何在Linux上搭建一个Git中央仓库
  8. c语言mysql自动重连接_c++操作mysql数据库
  9. (C语言)2066 分组统计
  10. 三星1万亿元重金下注,推动AI、5G、半导体等项目的研究
  11. Pandas DataFrame loc []访问一组行和列
  12. 数据库MySQL/mariadb知识点——操作篇(4)数据操作语句
  13. 实习成长之路:MySQL五:全局锁和表锁 :给表加个字段怎么有这么多阻碍?
  14. RHEL7.X双网卡绑定
  15. Java 设计模式 之 工厂方法模式、抽象工厂模式
  16. web逻辑思维题目_逻辑思维训练500题以及答案
  17. 初学Linux的简单命令(一)
  18. 初级java程序员面试题大全_Java初级程序员面试题大全
  19. 网课作业答案在哪找?手把手教你查大学网课作业答案~
  20. @loj - 2478@「九省联考 2018」林克卡特树

热门文章

  1. 运行时错误7内存溢出_C++程序运行时的内存模型
  2. splat net_Ruby中的Splat参数
  3. excel添加列下拉框票价_excel表格下拉表格添加数据-excel2017表格中怎么制作下拉菜单列表框...
  4. suse linux增加新磁盘分区,Virtualbox中Linux添加新磁盘并创建分区
  5. Java实现动态加载页面_[Java教程]动态加载页面数据的小工具 javascript + jQuery (持续更新)...
  6. dede plus ad js.php,织梦程序中plus文件作用介绍及安全设置
  7. IDEA 不为人知的 5 个骚技巧!真香!
  8. 【STM32】修改芯片型号后报 Error 的解决方案
  9. YOLO v3 安装并训练自己数据
  10. Buttons——CSS按钮样式库