從JVM上帝視角看Java中main()函數調用類方法限制

咱們都知道,除了靜態方法以外的全部方法都只能經過對象調用,沒用對象調用的確定是加了static關鍵字的靜態方法,static方法能夠經過類名調用。直接調用的話有兩種狀況,一是這個方法是包含main方法的類中的static方法,二是其餘類的static方法,但在文件開頭經過靜態導入static import導入了此方法所在的類。

1、爲何static修飾的能夠直接調用?

用static修飾的方法或屬性在程序執行時會先被加載到內存中,因此在main方法中能夠訪問到,而沒有用static修飾的方法或屬性只有在new 類名()的時候纔會在內存中分配地址,在內存中有了地址就能夠訪問了。java

2、本類中是否能夠直接調用方法?

下邊是初學java的朋友常犯的錯誤,也是疑惑最多的地方,現總結以下:算法

一、在本類中調用本身的方法,方法必須爲靜態的,不然報錯;編程

經過遞歸方法,實現N!的算法。數組

public class TestRecursion {
    public static void main(String[] args) {
        System.out.println(recursion(4));  //編輯器自動提示:Cannot make a static reference to the non-static method recursion(int) from the type TestRecursion
    }
    
    public int recursion(int n) {
        if(n == 1) {
            return 1;
        }else {
            return n * recursion(n-1);
        }
    }
}
必須將recursion()方法定義爲 static方法,才能在main()方法中直接調用。
public class TestRecursion {
    public static void main(String[] args) {
        System.out.println(recursion(4));
    }
    
    public static int recursion(int n) {
        if(n == 1) {
            return 1;
        }else {
            return n * recursion(n-1);
        }
    }
}

二、那麼,如何在main()方法中調用非靜態方法呢?
首先,實例化本類的對象,而後經過對象調用方法。編程語言

public class TestRecursion {
    public static void main(String[] args) {
        //首先是實例化本類的對象
        TestRecursion tr = new TestRecursion();
        //經過實例化的對象調用recursion()方法
        System.out.println(tr.recursion(4));
    }
    
    public  int recursion(int n) {
        if(n == 1) {
            return 1;
        }else {
            return n * recursion(n-1);
        }
    }
}

經過上面兩種方法,能夠解決在編程過程當中遇到的main()調用本類中的方法。編輯器

3、JVM如何調用java main方法

Main方法是咱們學習Java編程語言時知道的第一個方法,你是否曾經想過爲何main方法是publicstaticvoid的。固然,不少人首先學的是C和C++,可是在Java中main方法與前者有些細微的不一樣,它不會返回任何值,爲何main方式是public、static、void,這篇文章嘗試去找到一些答案。學習

Main方法是Java程序的入口,記住,咱們這裏不會討論Servlet、MIDlet和其餘任何容器管理的java程序,在java核心編程中,JVM會查找類中的public static void main(String[] args),若是找不到該方法就拋出錯誤NoSuchMethodError:main 程序終止。線程

Main方法必須嚴格遵循它的語法規則,方法簽名必須是public static void,參數是字符串數組類型,若是是Java1.5及之後的版本還可使用可變參數:設計

public static void main(String... args)

一、爲何main方法是靜態的(static)

正由於main方法是靜態的,JVM調用這個方法就不須要建立任何包含這個main方法的實例
由於C和C++一樣有相似的main方法做爲程序執行的入口。
若是main方法不聲明爲靜態的,JVM就必須建立main類的實例,由於構造器能夠被重載,JVM就無法肯定調用哪一個main方法。
靜態方法和靜態數據加載到內存就能夠直接調用而不須要像實例方法同樣建立實例後才能調用,若是main方法是靜態的,那麼它就會被加載到JVM上下文中成爲可執行的方法。code

二、爲何main方法是公有的(public)

Java指定了一些可訪問的修飾符如:privateprotectedpublic,任何方法或變量均可以聲明爲public,Java能夠從該類以外的地方訪問。由於main方法是公共的,JVM就能夠輕鬆的訪問執行它。

三、爲何main方法沒有返回值(Void)

由於main返回任何值對程序都沒任何意義,因此設計成void,意味着main不會有任何值返回

4、小結

  • 一、main方法必須聲明爲public、static、void,不然JVM無法運行程序
  • 二、若是JVM找不到main方法就拋出NoSuchMethodError:main異常,例如:若是你運行命令:java HelloWrold,JVM就會在HelloWorld.class文件中搜索public static void main (String[] args) 放法
  • 三、main方式是程序的入口,程序執行的開始處。
  • 四、main方法被一個特定的線程」main」運行,程序會一直運行直到main線程結束或者non-daemon線程終止。
  • 五、當你看到「Exception in Thread main」如:Excpetion in Thread main:Java.lang.NullPointedException ,意味着異常來自於main線程
  • 六、你能夠聲明main方法使用java1.5的可變參數的方式如:

public static void main(String... args)

  • 七、除了static、void、和public,你可使用final,synchronized、和strictfp修飾符在main方法的簽名中,如:

public strictfp final synchronized static void main(String[] args)

  • 八、main方法在Java能夠像其餘方法同樣被重載,可是JVM只會調用上面這種簽名規範的main方法。
  • 九、你可使用throws子句在方法簽名中,能夠拋出任何checked和unchecked異常
  • 十、靜態初始化塊在JVM調用main方法前被執行,它們在類被JVM加載到內存的時候就被執行了
相關文章
相關標籤/搜索