浅谈Java中的.java文件.class文件
今天想到一个问题为什么.class 文件中只有一个public修饰的类,之后查了很多资料,自己也做了不少测试,现在将所做的测试和结果和大家分享。
首先了解一下什么是.java文件,.class文件
类名.java文件是保存源代码的文本文件
使用 javac 类名.java可以编译该文件,编译为二进制字节码文件 类名.class
使用 java 类名 可以运行该类
类名.class是用于保存 Java类的 二进制编码以及Class对象,每一个 Java类都有一个解释该类特征的 Class对象。
创建一个java文件,文件名 Test.java,后面将不再说明。
测试一:.java文件中可以放public修饰的类?可以放默认修饰的类?min方法必须写在public修饰中的类中才能运行吗?
这是一个使用了public修饰的类:
- public class Test{
- public static void main(String[] args){
- System.out.println("你好!");
- }
- }
结果:我们看出可以进行编译、解析等正常运行
这是一个默认修饰符修饰的类
- class Test{
- public static void main(String[] args){
- System.out.println("你好!");
- }
- }
结果:我们看出可以进行编译、解析等正常运行
通过测试我们可以得到.java文件中可以定义public修饰的类和默认修饰的类,并且都可以使用min方法。
这里就会有人说这不废话吗;类的修饰符这么基础的东西谁不清楚。先别急,咱们接着往下看,
测试二:.java文件中可以有多个类吗?如果有那多个类修饰符应该怎么使用?
相信这个问题大家也都比较清楚,.class文件中public修饰的类只能存在一个,也就是.java文件如果存在多个public修饰的类,那么编译就是出错。
实例2.1:同时使用两个public修饰类无法通过编译。
- public class Test2{
- public static void main(String[] args){
- System.out.println("你好!");
- }
- }
- public class Test1{
-
- }
结果:我们可以看出这里就出现问题了。就是因为我们定义了两个public修饰的类。那么究竟是什么原因呢?
原因:
当编写一个java源代码文件时,此文件通常被称为编译单元。每个编译单元(文件)都只有一个public 类。因为每个编译单元都只能有一个公共接口,用public类来表现。该接口可以按照要求包含众多的支持包访问权限的类。如果有一个以上的public 类,编译器就会报错。 并且public类的名称必须与文件名相同(严格区分大小写)。 当然一个编译单元内也可以没有public类。
举一个不恰当的例子:你有一个房子(.java文件),房子只有一个入口(出口),这个入口必须且只有一个门(公共接口),且必须是可以上锁的(public),你是主人(虚拟机),你有一把钥匙可以决定谁能进去,但是钥匙多了囊?作为主人你愿意吗。肯定不愿意啦。
实例2.2:一个.java文件中可以有多个类,但只能有一个public修饰的类我们已经知道,那可以通过javac Test1.java 产生.class文件吗?
- public class Test{
- public static void main(String[] args){
- System.out.println("你好!");
- }
- }
- class Test1{
-
- }
答案是不能。实例:
原因:接着那个不恰当的例子来说,我的门是public的,你的钥匙也必须是public的,钥匙都不对,你还想进去?
实例2.3:如果类用public修饰,类名和文件名不一致则会报错:
- public class Test2{
- public static void main(String[] args){
- System.out.println("你好!");
- }
- }
可以看到出错了!原因也很简单,你有房,你也有钥匙,但是不好意思,这个不是你的房子,你跑错房子了。
通过测试我们可以的到之前所说的:.java 文件可以有多个类,但只能有一个public修饰的类,且public修饰的类必须和文件名相同(不带后缀)。如果编译单元中包含了public类,那么该类对应的字节码文件当需要被类加载器加载的,这时候就需要让类加载器知道该字节码文件的位置,所以就要确保该类与Java文件名称一致。同时,如果有两个public类在同一个文件中,而一个文件只能有一个名称,故两个public类的名称就不能同时和文件名一样,
测试三:.java文件中public修饰的类既然只有一个,那么我能不能不用public修饰其中的类。
答案是可以的,这个就不做测试;但是这个问题又引申出另一个问题,既然没有入口要求了,那么我们不使用public修饰类,这会有什么变化吗?
先说答案吧:java编译器在编译的时候,如果整个Java文件都没有public类(对外的公开接口类),类加载器子就无需从这方面直接去加载该编译单元产生的所有的字节码文件(.class文件),那么也就是无需去寻找编译后字节码文件存放位置。而类名和文件名一致是为了方便虚拟机在相应的路径中找到相应的类所对应的字节码文件。所以在没有public类的Java文件中,文件名和类名都没什么联系。
类名和文件名没有什么联系,这个直接体现就是:通过编译产生的二进制字节码文件和文件名无关。
- class Test2{
- public static void main(String[] args){
- System.out.println("你好!");
- }
- }
- class Test1{
- public static void main(String[] args){
- System.out.println("我很好!");
- }
- }
通过正常编译,并生成了两个class文件,
补充:从这我们可以看出,.java文件中有几个类就会生成几个class文件,如果是public修饰的话就一定会产生一个和文件名相同的.class文件。