Java在初期学习的时候,往往会因为一些规矩而导致错误频频,其实,在明白了为什么规矩如此之后,剩下的就简单多了。
再开始今天的话题,之前,我们先问几个问题:
1.一个java 文件为什么只能有一个public定义的类,是不是一个类文件中必须要定义一个public修饰的类(java 类有效修饰符有哪些?)?
2.main方法是否需要一定放在主类中?(主类是public修饰的类),main方法为何声明为static的?
3.为什么首先执行的是main方法(这里仅仅说下执行顺序,具体加载classLoader说起来太长,后续有需要再细化)?
先回答问题:
第一个:一个java文件中只能有一个public修饰的类,一个类文件不一定非得定一个一个pubic修饰的类,即如果不用public修饰,类名可以与类文件名不一致。
类的修饰符 只能为public/默认/abstract/final。
这里有的人要说了,static也能修饰类,记住,这里static修饰的类是内部类。
而且静态类里面的main方法也是可以程序执行的主入口的。
第二个:main方法不一定要放在主类中,main方法声明为static,是因为static方法不需要实例化类的对象就可以执行。通常情况下, 如果要运行一个类的方法,必须首先实例化出来这个类的一个对象,然后通过”对象名.方法名()”的方式来运行方法,但是因为main是程序的入口,这时候还没有实例化对象,因此将main方法声明为static的,这样这个方法就可以直接通过“类名.方法名()”的方式来调用。
第三个: 这是jvm的规范,简而言之,应该是一种约定。引用《深入jvm第二版》中的话说:java虚拟机实例通过调用某个类的main()来运行一个java程序,而这个main()必须是public static void并接受一个字符串数组作为参数,任何拥有这样一个main()的类都可以作为java程序的起点。
public static void main(String[] args)
主函数是一个特殊的函数,作为程序的入口,可以被jvm调用。
主函数的定义:
public:代表着该函数访问权限是最大的。
static:代表着主函数随着类的加载就已经存在了。
void:主函数没有具体的返回值。
main:不是关键字,但是一个特殊的单词,可以被jvm识别。
(String[] args):函数的参数,参数类型是一个数组,该数组中的元素类型是字符串类型。
主函数是固定格式的,jvm识别。
这里声明了main方法,也就是说 即使重载了同名的main方法,jvm只认规定的main方法来作为程序入口执行。
例证:
第一步,给出测试类 Test.java:
package com.generic;
public class Test{
static Object[]objs = new Object[2];
public static void main(String[] args) {
System.out.println("hello one");
System.out.println(objs.getClass().getClassLoader());
new Test().printClassloader(Test.class);
}
<T> void printClassloader(Class<T> t){
ClassLoader curLoader = t.getClassLoader();
if (curLoader != null && curLoader.getParent() != null && curLoader.getParent().getClass() != null) {
System.out.println(curLoader.getClass().getName());
System.out.println(curLoader.getParent().getClass().getName());
printClassloader(curLoader.getParent().getClass());
}
}
}
class Test2 {
public static void main(String[] args) {
System.out.println("hello2");
System.out.println();
}
}
class Test3{
static class Test4{
public static void main(String[] args) {
System.out.println("test4");
}
}
}
第二步:再看下类编译后的字节文件:
第三步:再看下执行入口
因此我们得知:
1.函数是从main函数开始运行的,并不是找public类中的main方法,
2.一个java文件即使没有公共类也是可以运行的,只要有main主函数就能运行,所以和是不是公共类没关系!
只不过public的类,java文件的名字要和类一致,只有这点不同。
3.有public的类,可以被别的包调用,而没有public的不能被别的包调用。
4.如果一个类就是单独运行的,和别的类没有关系,就不需要有public类。
5.一个java源文件中最多只能有一个public修饰的类,而且这个由public修饰的类必须与源文件名称相同,负责编译会报错。如果一个源文件中没有public修饰的类,则对类名称没有限制要求。
6.再次强调下,main方法不是必须要放在public修饰的类中。
7.至于为何一个源文件中只能含有一个与源文件同名的public修饰的类,这个是在编译的时候检测的,那么应该就是上文所说,是一种规则,可以从软件架构设计这个角度进行分析。