A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 高境 金牌黑马   /  2012-12-19 19:36  /  1978 人查看  /  9 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

1.为什么一个java文件中只能有一个public修饰的类?
2.为什么一个java文件中的类被public修饰了,这个java文件名要和类名相同?

评分

参与人数 2技术分 +1 黑马币 +14 收起 理由
曹佳佳 + 14 赞一个!
崔政 + 1 神马都是浮云

查看全部评分

9 个回复

正序浏览
public是公有类的,可以被被不同包中的类访问,当然也可以是protected修饰的类,这个得看你这个类自身的需要了
回复 使用道具 举报
清水 中级黑马 2012-12-21 19:53:24
9#
这样理解:
一个java文件在编译的时候,都会使用的其他的类,那么就需要查找其他类文件,加载到内存中。
如果发现有对应名称的class文件,就使用对应的class文件。如果没有找到对应的class文件,就将对应名称的java文件编译成对应的class文件。

如果java文件名和其中的类名不相符,java编译器为了找这个类,就有可能需要找很多java文件中,看是否有对应的类。这是相当低效的,而且也不安全(如果两个java文件都有同一个类,到底该使用那个呢?)。所以java文件名必须和其类名相符。为什么是public后面说。

java的体系是一层包一层,项目中有包,包中有java文件,java文件中有类,类里有成员变量和成员函数,成员函数中还有语句和变量。那么就需要对这些东西加上访问说明:
比如for(int x = 0; x<10;x++)这个里面的x到底是那个x呢,每个变量、方法、类、java文件都应该具备自己的一个影响、作用范围。所以才出现了public private等修饰符。
没有加publick的类,在这个java文件中可以使用。其他java文件就未必可以使用,但加了public的类,其他类也可以调用。再结合上面的java编译器查找类的一个过程,大概就可以理解为什么一个java文件只能有一个public类了。
回复 使用道具 举报
李培根 来自手机 金牌黑马 2012-12-20 20:22:22
8#
这个问题个人是这么理解的。
类被public修饰后类名必须要和java文件同名,所以一个java文件中只能有一个public修饰的类,因为有两个的话java文件的名字就不能确定。
而为什么public修饰的类,文件名要和类名相同,应该和反射机制有关,类加载器加载类文件的时候根据类名查找类文件。
回复 使用道具 举报
每个编译单元(文件)只能有一个public类。这么做的意思是,每个编
译单元只能有一个公开的接口,而这个接口就由其public类来表示。

我想这或是从软件架构设计和安全性设计上得出的结论。或者说是java的设计者们从这方面的考虑。或许这真的是一个规范,但我没有找到相关资料

不晓得到底有没有这一说话。如果有请知道的同行给出资料来源?

实验如下:
Test3.java源文件:
class Test1
{
int i = 1;


}

class Test2
{
int i = 2;
public static void main(String[] args)
{
  System.out.println("main method");
}
}

C:/javatest>javac Test3.java

C:/javatest>java Test2
main method

注:编译不会出错,注意是运行的Test2 因为没有Test3.class文件生成。如果运行Test3则报错

找不到该类
C:/javatest>java Test3
Exception in thread "main" java.lang.NoClassDefFoundError: Test3
Caused by: java.lang.ClassNotFoundException: Test3
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: Test3.  Program will exit.
这个错误原因很简单:JVM中的类加载器找不到Test3.class

同时这里也说明了包含main()的类如果想运行则不一定要是public的。



《深入jvm第二版》中有这样一句话:
java虚拟机实例通过调用某个类的main()来运行一个Java程序,而这个main()必须是public
static void 并接收一个字符串数组作为参数,任何拥有这样一个main()的类都可以作为java程

序的起点。
并没有说拥有main()方法的类一定要是public类。


Test7.java源文件:
class Test5
{
int i = 1;


}

public class Test6
{
int i = 2;
public static void main(String[] args)
{
  System.out.println("main method");
}
}

如果运行Test7.java 报错:
C:/javatest>javac Test7.java
Test7.java:8: 类 Test6 是公共的,应在名为 Test6.java 的文件中声明
public class Test6
        ^1 错误
这里说明了文件名必须与public类的类名一致,(如果文件中有public类)

这里可以看出如果有多个public类,那么文件名应该是哪个public类的呢?显然一个java源文件

只能有一个public类。

所以总结如下:一个Java源文件中最多只能有一个public类,当有一个public类时,源文件名必

须与之一致,否则无法编译,如果源文件中没有一个public类,则文件名与类中没有一致性要求。
至于main()不是必须要放在public类中才能运行程序。

以上是通过实验得出的结论,个人认为到这里已经可以了,如果一定要追问到底,可能要问问java

平台的设计者了。或许,人家会说:这是java的设计和jvm的内部体系结构设计造成,这是一个规

范,没有为什么。

评分

参与人数 1黑马币 +1 收起 理由
高境 + 1 很给力!

查看全部评分

回复 使用道具 举报
我觉得吧,初期学java现在没必要拘泥于这些问题,把它当做是一个规则,该怎么办就怎么办,就像小时候刚入学就问1+1为什么等于2,没多大意思。
回复 使用道具 举报
java程序。。打错了 刚才。改正下。
回复 使用道具 举报
ava程序是从一个public类的main函数开始执行的,(其实是main线程),就像C程序是从main()函数开始执行一样。
只能有一个public类是为了给类装载器提供方便。我自己的理解是这样的:一个public 类只能定义在以它的类名为文件名的文件中。 class a 表示默认的访问级别,即只有包内的其他类能访问它 (严格来说应该是 class A,类名一般大写)小应用程序只有一个类,一方面是因为定义的类越多,程序执行就越缓慢(需要多装载几个类),另一方面是为了处理的方便,因为只有一个类时,编译之后就只有一个.class文件,如果是多个类,编译之后就有几个.class文件,这时候就要打包成.jar文件,再添加到相应的 HTML文件标记中,这样显然更麻烦了,,不是吗?另外作为程序入口的类不一定要public类,只要是执行时Classloader能找到,有权访问的类及main方法就行、public指定的类必须是以同类名的文件名来保存,所以不能有多个public类。
回复 使用道具 举报
不错,问的好
回复 使用道具 举报
1 用public修饰的类都是该文件名的前缀,且一个文件只能有一个文件名!不知道说的对不对,只做参考。

还有这就是个规定,应该涉及到了jvm的原理问题,还是找高手回答吧,凑凑热闹!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马