Knowledge Point 20180303 详解main函数

  学习Java的朋友想来都是从HelloWorld学起的,那么想来都对main函数不陌生了,但是main函数究竟是怎么回事呢?main函数中的参数是做什么的呢?main函数为什么能作为程序的入口呢?可不可以存在多个main函数呢?下面我们就来对main函数进行一些深入的了解.

1.Java中的main()方法详解

  在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的方法有很大的不同,比如方法的名字必须是main,方法必须是public static void 类型的,方法必须接收一个字符串数组的参数等等。在看Java中的main()方法之前,先看一个最简单的Java应用程序HelloWorld,我将通过这个例子说明Java类中main()方法的奥秘,程序的代码如下:

/** 
* Java中的main()方法详解 
*/ 
public class HelloWorld { 
    public static void main(String args[]) { 
        System.out.println("Hello World!"); 
    } 
}

1.1 先说类:

  HelloWorld 类中有main()方法,说明这是个java应用程序,通过JVM直接启动运行的程序。既然是类,java允许类不加public关键字约束,当然外部类的定义只能限制为public或者无限制关键字(默认的)。

1.2 再说main()方法

  这个main()方法的声明为:public static void main(String args[])。必须这么定义,这是Java的规范。为什么要这么定义,和JVM的运行有关系。当一个类中有main()方法,执行命令“java 类名”则会启动虚拟机执行该类中的main方法。由于JVM在运行这个Java应用程序的时候,首先会调用main方法,调用时不实例化这个类的对象,而是通过类名直接调用因此需要是限制为public static。对于java中的main方法,jvm有限制,不能有返回值,因此返回值类型为void。main方法中还有一个输入参数,类型为String[],这个也是java的规范,main()方法中必须有一个入参,类型必须String[],至于字符串数组的名字,这个是可以自己设定的,根据习惯,这个字符串数组的名字一般和sun java规范范例中mian参数名保持一致,取名为args。因此,main()方法定义必须是:“public static void main(String 字符串数组参数名[])”。

1.3 main()方法中可以throw Exception

  因此main()方法中可以抛出异常,main()方法上也可以声明抛出异常。比如,下面这个写法是正确的:

public class TestMain { 
        public static void main(String[] args) throws Exception { 
                System.out.println("哈哈哈哈哈"); 
                throw new Exception(""); 
        } 
}
运行结果:
哈哈哈哈哈 
Exception in thread "main" java.lang.Exception:    
  at maintest.TestMain.main(TestMain.java:11) 
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
  at java.lang.reflect.Method.invoke(Method.java:585) 
  at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90) 
Process finished with exit code 1

1.4 main()方法中字符串参数数组作用

  main()方法中字符串参数数组作用是接收命令行输入参数的,命令行的参数之间用空格隔开。下面给出一个例子,看看如何初始化和使用这个数组的。

/**
* 打印main方法中的输入参数 
*/ 
public class TestMain { 
    public static void main(String args[]){ 
        System.out.println("打印main方法中的输入参数!"); 
        for(int i=0;i<args.length;i++){ 
            System.out.println(args[i]); 
        } 
    } 
}
执行方法和运行结果
D:\Study\basetest\src>javac TestMain.java
D:\Study\basetest\src>java TestMain 1 2 3 
打印main方法中的输入参数! 


1.5 给出HelloWorld的另外一个版本

/** 
* 变态版的HelloWorld.呵呵 
*/ 
public class HelloWorld2 { 
    static { 
        System.out.println("Hello Wordld!"); 
    } 
    public static void main(String args[]){ 
        System.exit(0); 
    } 
}

  这个main()方法执行的内容就一句"System.exit(0);" ,目的是让程序正常结束。那“HelloWorld!”是从哪里打印的,秘密就是在static打印的,因为static代码块的内容会在main调用前调用。这其实涉及到了代码块,关于代码块,我们放在面向对象之后讲解;

1.6 解读main

  上面我们对main有了一个认识,那么我们下面来认识一些main函数中的一个核心字main,main并不是Java中的关键字,他只是一个方法名,那么我们知道方法在类中是会存在重载的,那么main函数可以重载吗?以一段代码为例:

package main.practice;

public class TestMain {
    public static void main(String[] args) {
        System.out.println("打印main函数中的参数!");
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
        main();
    }
    public static void main(){
        System.out.println("main函数重载!");
    }
}

  通过上面我们知道这是可以的,也就是说main函数只是Java规定的特定格式的能够被JVM识别的一个特殊方法,用来作为程序的入口,除此之外遵循Java的其他特性.在java中,main()方法是java应用程序的入口方法。java虚拟机通过main方法启动一个线程(该线程名为main)找到需要启动的运行程序,并且检查main函数所在类是否被java虚拟机装载。如果没有装载,那么就装载该类,并且装载所有相关的其他类。因此程序在运行的时候,第一个执行的方法就是main()方法。通常情况下, 如果要运行一个类的方法,必须首先实例化出来这个类的一个对象,然后通过"对象名.方法名()"的方式来运行方法,但是因为main是程序的入口,这时候还没有实例化对象,因此将main方法声明为static的,这样这个方法就可以直接通过“类名.方法名()”的方式来调用。虚拟机通过调用某个指定类的方法main启动,传递给main一个字符串数组参数,使指定的类被装载,同时链接该类所使用的其它的类型,并且初始化它们。例如对于程序:

复制代码
public class HelloApp {
    public static void main(String[] args) {
        System.out.println("Hello World!");
        for (int i = 0; i < args.length; i++) {
            System.out.println(args);
        }
    }
}
复制代码

  编译后在命令行模式下键入: java HelloApp run virtual machine

  将通过调用HelloApp的方法main来启动java虚拟机,传递给main一个包含三个字符串"run"、"virtual"、"machine"的数组。现在我们略述虚拟机在执行HelloApp时可能采取的步骤。开始试图执行类HelloApp的main方法,发现该类并没有被装载,也就是说虚拟机当前不包含该类的二进制代表,于是虚拟机使用ClassLoader试图寻找这样的二进制代表。如果这个进程失败,则抛出一个异常。类被装载后同时在main方法被调用之前,必须对类HelloApp与其它类型进行链接然后初始化。链接包含三个阶段:检验,准备和解析。检验检查被装载的主类的符号和语义,准备则创建类或接口的静态域以及把这些域初始化为标准的默认值,解析负责检查主类对其它类或接口的符号引用,在这一步它是可选的。类的初始化是对类中声明的静态初始化函数和静态域的初始化构造方法的执行。一个类在初始化之前它的父类必须被初始化。整个过程如下:

总结:

  main方法作为一个特殊的规范,与普通的方法有很大区别,限制很多,他是一种特殊规格的函数,能够被JVM识别,作为程序的入口,main方法仍然遵循Java的重载等特性,是一种特定格式的函数!在一个java项目中可以存在多个这种特定格式的main函数,但一个类中只能有一个这样格式的main函数,JVM运行当前类时,找到这个main函数作为程序入口(实际上是启动一个线程来运行我们的代码,该线程中可以包含其它线程),然后依次执行,!

转载自:http://lavasoft.blog.51cto.com/62575/53263/

    http://www.cnblogs.com/xwdreamer/archive/2012/04/09/2438845.html

posted @ 2018-03-03 16:55  十月十四  阅读(536)  评论(0编辑  收藏  举报