我对Java中main方法的疑惑及理解

本文探讨了Java中main方法的疑惑,从访问权限、静态修饰、返回值和参数列表等方面进行分析。揭示了main方法作为程序入口的本质,即一个被JVM自动调用一次的静态方法。同时,文章通过实例解释了如何在main方法中实例化当前类,并讨论了main方法与其他静态代码块的执行顺序以及程序员如何手动调用main方法。最后得出结论,main方法只是一个普通的静态方法,但其特殊之处在于被JVM自动调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

疑惑的产生

每一个Java学习者都知道程序的入口是public static void main(String[] args){}注1,包括我自己,但是有C++基础的我对main产生了一些疑问

public class MainMethod {
    final int a = 0;
    private void print_a(){
        System.out.println(a);
    }
    public static void main(String... args) {
        MainMethod mObj = new MainMethod();
        mObj.print_a();
    }
}

我的疑惑来自于类似于上面代码的结构,无法理解为什么可以在main中实例化main所在类(MainMethod mObj = new MainMethod();),
询问得到的结果是:“Java的规定罢了”,这样相当于没回答的回答无法解决问题,于是开始自己研究。


通过写法分析main方法

    public static void main(String... args) {
      //方法体
    }
  • public:访问权限修饰符,公共的,给main方法最高的访问权限。为了保证JVM在任何时候都可以访问main方法,所以使用public修饰。
  • static:静态的,方法被static修饰符修饰后不需要通过实例调用。这样在类加载的时候main方法就已经准备好了(存储在方法区而非堆内存中),换句话说,JVM想要调用main方法不需要实例化main所在类而只需要加载main所在类。这可以使调用更方便。
  • void:由于Java默认退出代码为0,所以不需要像C++一样返回int,无异常程序结束退出代码0,异常结束退出代码1
  • main:这个还真是*“Java的规定罢了”*
  • **(String... args):程序的入口有参数列表的原因是通过命令行启动Java时是可以带参数启动的,比如java MainMethod aweee这样的启动方式,aweee就会作为参数传入main方法。默认启动的时候args为空。

main方法的调用及main的本质理解

为什么程序可以执行?
main方法是程序的入口,就是说main方法可以被JVM识别并调用,可以理解为在程序一切的一切开始之前JVM先执行了类名.main(参数);(这个说法并不严谨,事实上在main之前还有static代码块执行)而在JVM第一次调用之后,JVM便不会主动调用main方法,但是!程序员仍然可以调用main方法! 程序员也可以调用别的类的main方法!

这直接说明main本质上只是一个普通的静态方法,只不过被自动调用了一次。

public class MainMethod {
    static { System.out.println("static代码块执行了!"); }
    
    public static void main(String... args) {
        System.out.println("main方法执行了");
    }
    /*输出:
	static代码块执行了!
	main方法执行了
	*/
}

上面的例子体现main的自动调用和main与static代码块的执行顺序。

public class MainMethod {
    public static void main(String... args) {
        System.out.println("main方法执行了");
        MainMethod.main("");
    }
    /*输出:
    main方法执行了
    main方法执行了
    main方法执行了
    ......
     */
}

上面的例子展示了main作为普通静态方法调用,事实上上例形成了可怕的递归,理论上来说“main方法执行了”会无限输出,不过程序因异常结束了:(

/* TestClass.java */
public class TestClass {
    public static void main(String... args) {
        System.out.println("TestClass.main(String... args);调用");
    }
}
/* MainMethod.java */
public class MainMethod {
    public static void main(String... args) {
        TestClass.main("");
    }
}
//输出:TestClass.main(String... args);调用

上面的例子展示了调用其他类的main。


在main中实例化main当前类

import java.lang.reflect.Method;

public class MainMethod {
    final int a = 0;
    private void print_a(){
        System.out.println(a);
    }
    public static void main(String... args) {
        MainMethod mObj = new MainMethod();
        mObj.print_a();
        System.out.println("\nMainMethod类中定义的方法有:");
        for(Method i :mObj.getClass().getDeclaredMethods()){
            System.out.println(i.getName());
        }
    }
    /* 输出:
    0

	MainMethod类中定义的方法有:
	main
	print_a*/
}

回到开头那个例子,通过调试发现main也只不过是MainMethod类中定义的一个方法罢了。


结论:

我把问题复杂化了,main就是个被自动调用一次的普通静态方法而已。


注:

注1:args可以改名,String[] args可以写成String args[]←C-style,高版本Java可以写成String... args


参考资料(按日期排列)

Java main方法
解析java中main函数为什么是这样写
java中main方法的理解
Java-程序的入口main方法
详解Java的main函数
Java–主函数(main)

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值