当编写一个java源代码文件时,此文件通常被称为编译单元(有时也被称为转译单元)。每个编译单元都必须有一个后缀名.java,而在编译单元内则可以有一个public类,该类的名称必须与文件的名称相同(包括大小写,但不包括文件的后缀名.java)。每个编译单元只能有一个public类,否则编译器就不会接受(即只能有0-1个public类)。如果在该编译单元之中还有额外的类的话(即其他非public类),那么在包之外的世界是无法看见这些类的,这是因为它们不是public类,而且它们主要用来为主public类提供支持。
首先说一下为什么public的类名要与.java文件名一致的问题~
B.java文件
package com.culiu.ccj.servant.tagstatistics.test; /**
* 描述:
* 创建人: BruceCloud
* 创建时间: 2016/5/18 10:10.
*/
public class B {
} class C{
}
Test.java文件
package com.culiu.ccj.servant.tagstatistics.test.aa; import com.culiu.ccj.servant.tagstatistics.test.B; /**
* 描述:
* 创建人: BruceCloud
* 创建时间: 2016/5/18 10:10.
*/
public class Test {
public static void main(String[] args) {
try {
B a = new B();
// C c = new C();
Class c = Class.forName("com.culiu.ccj.servant.tagstatistics.test.C");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
上面代码B.java中, 有2个类(public B和非public的 C), 在B.java这个编译单元中, public B是该编译单元对外的接口类, C则是包内使用的类, 根据java的编程规则, 在Test.java中第14行引入C时会编译出错, 提示你找不到C这个类, 因为C没有被public修饰,
所以C只能在com.culiu.ccj.servant.tagstatistics.test包下面使用, 而第13行B却可以使用, 因为在使用B的时候在上面使用了import com.culiu.ccj.servant.tagstatistics.test.B;对B进行了导入(可以导入的前提是com.culiu.ccj.servant.tagstatistics.test.B
这个编译单元提供了对外公开的接口, 即public修饰的类), 而你使用import com.culiu.ccj.servant.tagstatistics.test.C;的时候会报错, 提示你找不到C, 因为不存在com.culiu.ccj.servant.tagstatistics.test.C这个编译单元(即使存在也不存在public入口)~~
接下来在程序运行到Test.java第13行时, jvm会去加载B这个类, 而加载的方式就是通过import后面的编译单元名称进行加载的(即通过com.culiu.ccj.servant.tagstatistics.test.B进行加载的, 加载的内容就是该编译单元的入口类, 就是public修饰的类), 所以
public修饰的的类名必须要与.java文件名一致, 就是为了方便在加载编译单元入口类的时候不用在进行名字转换了, 这样省了很多麻烦, 直接去加载com.culiu.ccj.servant.tagstatistics.test.B.class就行了, 而无需在进行名字转换~~~
试想一下, 如果B.java中的public类的名字是C, 那么在加载编译单元B的时候还需要去查找编译单元B的入口类名字, 假想步骤如下:
1.取得编译单元B的位置import com.culiu.ccj.servant.tagstatistics.test.B;
2.再在1的位置中找到要加载的入口类(此时因为public的类名跟B.java的文件名不一致, 所以无法直接通过1中的com.culiu.ccj.servant.tagstatistics.test.B.class来加载了, 需要进行
入口类的名称查找或者转换, 最终加载的也就是com.culiu.ccj.servant.tagstatistics.test.C.class)
这样会很麻烦~~莫不如直接规定public的类与.java文件名相同~~~
PS: 上面Test.java中有一点需要注意, 虽然B.java中的C类无法在其他包下使用, 但是却可以在其他包下通过反射来进行加载~~如第15行~~
到此, 为什么public类名必须和.java文件名相同的问题讲完了~~
接下来讲为什么.java文件中只能有一个public类~~~
因为在文件系统中, 一个文件只能有一个名字, 这里的情况就是一个编译单元(即.java文件)只能有一个名, 而这个名字的作用恰好还是jvm用来加载该编译单元入口类的, 而上面讲了jvm在
加载编译单元入口类的时候是通过编译单元名字来进行加载的, , 所以如果你的编译单元中有多个public类(即有多个入口), 那么jvm就无法分辨到底要去加载哪个入口类了~~
到此, 为什么.java文件中只能有一个public类的问题讲完了~~
写在最后:
以上内容都是本人自己的理解, 不敢保证java设计者们就是这么想的, 我写出的目的也方便日后自己忘了的时候还能翻出来此文再来回想一下曾经的想法~~
欢迎各路Java大神来讨论一下并留下自己的理解~~一切的一切都是以最终能搞明白问题的本质为目的~~所以还请口下留情~~
Java文件中为什么只能有一个public修饰的类, 并且类名还必须与文件名相同的更多相关文章
-
一个java源文件中为什么只能有一个public类。
我们都遇到过一个源文件中有多个java类,但当第一个类使用public修饰时,如果下面还有类使用public修饰,会报错.也就是是说一个java源文件最多只能有一个public类. 当有一个publi ...
-
java-源文件中可以有多个类,但是最多只能有一个public修饰
1.如果源文件中有多个类,那么只能有一个类是public类:如果有一个类是public类,那么源文件的名字必须与这个类的名字完全相同,扩展名是.java. 2.如果源文件中没有public类,那么源文 ...
-
第7章 一个java源文件中只能有一个public类
一个Java源文件中最多只能有一个public类, 1)当有一个public类时,源文件名必须与之一致,否则无法编译, 2)如果源文件中没有一个public类,则文件名与类中没有一致性要求. 至于ma ...
-
浅谈为什么一个java源文件中只能有一个public类?
声明,本篇文章为转载 转载 http://blog.csdn.net/bareheadzzq/article/details/6562211 最近在一个java文件中实现了几个类,其中一个声明为pub ...
-
为什么一个java源文件中只能有一个public类
问题:一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 答案:可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致.一个文件 ...
-
一个.java文件中可以有几个同级类
1.在一个.java文件中可以有几个类.修饰符只可以public abstract final和无修饰符,不能是其他的private等修饰符.2.public修饰的只能有一个,且要与文件名相同 若没有 ...
-
一个.java文件中是否可以有多个类
前段时间,有个同事问到我这个问题:一个.java文件中是否可以有多个类? 答案:可以有多个类,但最多只能有一个被public修饰的class. 且若这个.java文件中有一个public类型的clas ...
-
一个项目中:只能存在一个 WebMvcConfigurationSupport (静态文件失效之坑)
一个项目中:只能存在一个 WebMvcConfigurationSupport 在一个项目中WebMvcConfigurationSupport只能存在一个,多个的时候,只有一个会生效. 静态文件访问 ...
-
JAVA文件中获取路径及WEB应用程序获取路径方法
JAVA文件中获取路径及WEB应用程序获取路径方法 1. 基本概念的理解 `绝对路径`:你应用上的文件或目录在硬盘上真正的路径,如:URL.物理路径 例如: c:/xyz/test.txt代表了tes ...
随机推荐
-
solr 添加索引
添加索引模板: <add> <doc> <field name="employeeId">05991</field> <fie ...
-
Java开发11个过不去的梗
现在随着编程的普及,作为java程序猿开发的过程逐渐的受到领导的重视,无论自己的经理是能看懂,还是不能看懂,一些事项必须注意起来,不要让自己将来处于不尴不尬的境地,当然这样也方便你我他 1.不在属性文 ...
-
[转载]寻找两个有序数组中的第K个数或者中位数
http://blog.csdn.net/realxie/article/details/8078043 假设有长度分为为M和N的两个升序数组A和B,在A和B两个数组中查找第K大的数,即将A和B按升序 ...
-
Sql2008 php
Sql2008支持php的擴展插件 http://www.microsoft.com/download/en/search.aspx?q=SQL+Server+for+PHP 全部 http://w ...
-
ubuntu 安装完成后的工作
以安装 ubuntu 15.10 为例 1. 备份并更改源 cd /etc/apt sudo cp source.list source.list.bak sudo vi source.list 删除 ...
-
字符串截取 方法 String b=a.substring(0, a.indexOf(";乘坐";));
String b=a.substring(0, a.indexOf("乘坐"));
-
《算法导论》归并排序----merge-sort
伪代码请见<算法导论>2.3节 merge-sort实现: public class MergeSort { public static void sort(double [ ...
-
Linux Redis 重启数据丢失解决方案,Linux重启后Redis数据丢失解决方
Linux Redis 重启数据丢失解决方案,Linux重启后Redis数据丢失解决方案 >>>>>>>>>>>>>> ...
-
SpringMVC返回json数据的三种方式(转)
原文:https://blog.csdn.net/shan9liang/article/details/42181345# 1.第一种方式是spring2时代的产物,也就是每个json视图contro ...
-
(网页)java数组去重总结(转)
转自CSDN: 1.背景 根据不同的业务逻辑,经常会遇到数组中存在多个重复元素的场合,总结了下数组的排序,留个记录. 2.实现方法 总结了四种方法,接下来进行展示 1.方法一 //数组去重方法一 ...