main方法是我们最熟悉的方法了。从最初的开始入门Java开始就接触它了,main方法是Java程序的入口点,由Java虚拟机自动调用。因此,在很多人眼里,将main方法当作为神秘的方法,认为该方法具有很多特殊性。那么,事实是否真如此呢?你有去想过么?
本文我们就一起来深挖一下main方法相关的知识。
在JDK1.5
前,声明方式
public class MainTest {
public static void main(String[] args) {
System.out.println("main");
}
}
还可以另外一种方式:
public class MainTest {
public static void main(String args [] ) {
System.out.println("main");
}
}
其实上面的两种方式还是一种,区别在于Java中数组声明的方式不同罢了。
在JDK5
及以后
public class MainTest {
public static void main(String ... args) {
System.out.println("main");
}
}
哈哈,很多人都没想到吧,其实就是可变参数吧。
请看以下代码:
public class MainTest {
private static void main(String ... args) {
System.out.println("main");
}
}
把public换成private。有问题吗?代码能正常运行吗?
答案是不能正常运行,找不到程序入口。也就是在eclipse和IDEA中运行的时候找不到Run 和Debug了。
public:main方法作为应用程序的入口,该方法是程序启动时候由Java虚拟机调用的,所以访问权限当然是需要设置为public。
static:如果不是静态的方法,就需要通过对象来调用。而当Java程序运行,虚拟机调用main方法的时候,没有必要创建含有main方法类的对象。例如:类A中声明了main方法,当运行类A的时候,虚拟机直接调用类A的main方法,没有必要创建A对象,然后通过对象调用main方法。
void:main方法在退出时,并没有给系统返回退出代码,而是在需要时候使用System.exit(int status);方法来返回,所以返回类型为void。
String [] args:该字符串数组用来运行时接收用户输入的参数,具体长度取决于用户输入的参数的长度,如果用户没有输入参数,则长度为0.
说到“特殊性”,main方法是Java虚拟机在程序启动的时候自动调用的,并且在命令行可以传递参数给main方法的args
参数,从这点就可以说明,main方法和其他方法是不一样的。不过,在更多的表现上 ,main方法与普通的方法是一样的。
例如:
关于重载的概念,这里就不提了,不清楚请自行学习。
如果没有按照上面所述的三种方式来声明main方法,会发生怎样的情况呢?
public class MainTest {
public int main(int i) {
System.out.println("main 2 " + i);
return i;
}
public static void main(String arg) {
System.out.println("main 3");
}
//如果没有下面这个方法,只有上面两个方法是没法启动程序的,
//会提示:在类com.tian.swagger.advancedfeatures.thisandsuper.MainTest中
//找不到主方法
public static void main(String[] args) {
System.out.println("main 1");
}
}
也就是说,Java虚拟机要求的main方法必须是按照前面说的三种声明方式,否则,将认为你没有给程序定义好入口(main方法)。
我们都只是在main方法中调用其他方法,那么其他方法能不能调用main方法呢?
public class MainTest {
private static boolean flag = true;
public static void test() {
if (flag) {
flag = false;
//调用main方法
main(new String[]{""});
}
}
public static void main(String[] args) {
System.out.println("main");
test();
}
}
输出:
main
main
说明其他普通方法也是能调用main方法的。
public class Base {
public static void main(String[] args) {
System.out.println("base main");
}
}
public class Sub extends Base {
}
在Sub类中Run也是可以的,并且输出:
base main
说明main方法是可以继承的。
隐藏main方法
如果子类继承了父类的main方法,并且在子类中重写声明新的main方法,也可以隐藏父类的main方法,这个与隐藏其他方法一样的。
public class Base {
public static void main(String[] args) {
System.out.println("base main");
}
}
public class Sub extends Base {
public static void main(String[] args) {
System.out.println("sub main");
}
}
在Sub中Run,输出:
sub main
public class MainTest {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.tian.swagger.MainTest");
}
}
说明main方法和普通方法一样,都可以抛出异常的。
public class MainTest {
private static boolean flag = false;
public static <T> void main(String[] args) {
if (flag) {
System.out.println("main exit");
System.exit(0);
} else {
test(args);
}
}
private static void test(String[] args) {
flag = true;
MainTest.<String>main(args);
}
}
MainTest
可以Run,并且输出:
main exit
声明两个main方法
public class MainTest {
public static void main(String[] args) {
}
public static void main(String ... args) {
}
}
猜想上面这段代码有问题吗?
Java语言中作为程序入口的main方法,需要将其声明为public,static,void,并且方法参数类型为String数组或可变String类型参数。在程序启动的时候,Java虚拟机自动调用main方法。
main方法在表现行为上,与其他普通方法基本相同,可以重载、由其他方法调用、继承、隐藏。也可以抛出异常、带有类型参数。
可以使用反射来调用main方法,(这里没实现,有兴趣的小伙伴自己去尝试)。
不能在同一个类中声明两个main方法(main三种正确声明方式中的两种),否则,抛异常:
Error:(14, 26) java:
无法在com.tian.swagger.MainTest中同时声明main(java.lang.String...)
和main(java.lang.String[])