1. 程式人生 > >JDK原始碼學習-基礎類

JDK原始碼學習-基礎類

一、概述

  1、Java,是一套語言規範,例如規定了變數如何定義、控制語句如何寫等,提供基本的語法規範。JDK是java自帶的一套呼叫元件,是對基本java語法規範的進一步封裝,jdk中都是使用java基本的語法來寫的,使用JDK能夠更好的使用java。當然,自己也可以寫一套JDK。自己在專案中也可以不使用自帶的JDK,而使用原生的基本語法。

  2、在整個JDK API中,大約包含1200個包,包名主要有三種:java、javax和org。其中以java開頭的包名是JDK的基礎語言包,以javax開頭的屬於JDK擴充套件包(其中x是extend的簡寫),而以org開頭的則是第三方組織提供的功能包(org是organization的簡寫)。而在JDK API中還包含了一些以com.sun開頭的包名,這些是SUN公司提供的一些功能包,由於這些包中的類隨著JDK版本的更改變化很大,不具備相容性,所以未在標準的JDK API文件中進行公開。

  3、rt.jar檔案是java執行時類庫,是我們用到最多的基礎類庫,包括java.lang,java.io,java.net,java.util等。

    java.lang:Java語言包,這個包下的檔案不需要顯式import。包括:Object類,資料型別相關的類(String,Long,Byte),Class類,執行緒相關類Thread,異常類Throwable,等。

    java.io:I/O操作相關的類。包括:檔案類File,FileReader,FileWriter,輸入輸出流InputStream/OutputStream,等。

    java.net:網路相關類。包括:http連線類HttpURLConnection,socket類,等。

    java.util:工具類。包括:資料結構相關的類ArrayList、Hashmap,日期類Date,隨機數類Random,等。

  4、java native方法:不由java實現的方法,一般這些方法都是很底層,跟平臺結合緊密,或者使用java實現效能很差。   二、Object類   1、Object類是java中所有類的父類,所有類預設繼承Object。這也就意味著,Object類中的所有公有方法也將被任何類所繼承。如果,整個java類體系是一顆樹,那麼Object類毫無疑問就是整棵樹的根。   Object類中的方法如下:   
  三、Class類   1、先複習幾個概念:     類:事物特徵的抽象,可以理解為模板,是事物特徵的定義。可以建立物件。     物件:是一個具體的事物實體,由類建立的。   2、Class類也是一個抽象的事物定義,也是類的一種,同String類以及自己定義的類是一樣的。只是名字和class關鍵字高度相似。Java是大小寫敏感的語言。   3、Java程式在執行時,需要記錄已經載入的類的資訊,這些資訊也會使用物件來記錄,這個物件就由Class類來建立。Class類建立的物件是用來記錄類的資訊的。比如你建立一個shapes類,那麼,Java會生成一個內容是shapes的Class類的物件,用來記錄shapes的狀態等資訊。   4、Class類的物件不能像普通類一樣,以 new shapes() 的方式建立,它的物件只能由JVM建立,因為這個類沒有public建構函式。   5、一個類的多個物件只會有一個Class物件。每個類都有一個Class物件。   6、基本的 Java 型別(boolean、byte、char、short、int、long、float 和 double)和關鍵字 void 也都對應一個 Class 物件。 
      7、每個陣列屬於被對映為 Class 物件的一個類,所有具有相同元素型別和維數的陣列都共享該 Class 物件。   8、使用Class.forName(),載入一個類到記憶體中,使用newInstance()建立類。newInstance()方法呼叫預設構造器(無引數構造器)初始化新建物件。   9、java裡面任何類都要裝載在虛擬機器上才能執行。forName就是裝載類用的(new是根據載入到記憶體中的類建立一個例項,要分清楚)。 至於什麼時候用,可以考慮一下這個問題,給你一個字串變數,它代表一個類的包名和類名,你怎麼例項化它? A a = (A)Class.forName("pacage.A").newInstance();這和A a = new A();是一樣的效果。   10、jvm在裝載類時會執行類的靜態程式碼段,要記住靜態程式碼是和類繫結的,類裝載成功就表示執行了你的靜態程式碼了,而且以後不會再執行這段靜態程式碼了。   11、Class.forName(xxx.xx.xx)的作用是要求JVM查詢並載入指定的類,即查詢對應的.class檔案,也就是說JVM會執行該類的靜態程式碼段。
  12、動態載入和建立Class物件,比如想根據使用者輸入的字串來建立物件
         String str = 使用者輸入的字串  
         Class t = Class.forName(str);  
         t.newInstance(); 
  13、在初始化一個類,生成一個例項的時候,newInstance()方法和new關鍵字除了一個是方法,一個是關鍵字外,它們的區別在於建立物件的方式不一樣,前者是使用類載入機制,後者是建立一個新類。這主要考慮到軟體的可伸縮、可擴充套件和可重用等軟體設計思想,才有這兩種建立方式。Java中工廠模式經常使用newInstance()方法來建立物件,因此從為什麼要使用工廠模式上可以找到具體答案。例如:
           Class c = Class.forName(“Example”);  
           factory = (ExampleInterface)c.newInstance();  
       其中ExampleInterface是Example的介面,可以寫成如下形式:
          String className = "Example";  
          class c = Class.forName(className);  
          factory = (ExampleInterface)c.newInstance();  
      進一步可以寫成如下形式:
         String className = readfromXMlConfig;//從xml 配置檔案中獲得字串
         class c = Class.forName(className);  
         factory = (ExampleInterface)c.newInstance();  
        上面程式碼已經不存在Example的類名稱,它的優點是,無論Example類怎麼變化,上述程式碼不變,甚至可以更換Example的兄弟類Example2 , Example3 , Example4……,只要他們繼承ExampleInterface就可以。  
  14、從JVM的角度看,我們使用關鍵字new建立一個類的時候,這個類可以沒有被載入。但是使用newInstance()方法的時候,就必須保證:這個類已經載入和這個類已經連線了。而完成上面兩個步驟的正是Class的靜態方法forName()所完成的,這個靜態方法呼叫了啟動類載入器,即載入 java API的那個載入器。現在可以看出,newInstance()實際上是把new這個方式分解為兩步,即首先呼叫Class載入方法載入某個類,然後例項化。這樣分步的好處是顯而易見的。我們可以在呼叫類的靜態載入方法forName時獲得更好的靈活性,提供給了一種降耦的手段。  
  15、用最簡單的描述來區分new關鍵字和newInstance()方法的區別:
  newInstance: 弱型別。低效率。只能呼叫無參構造。  
  new: 強型別。相對高效。能呼叫任何public構造。   簡單例項如下:
public class People {

  private String name;
  private int age;
  private String gender;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public String getGender() {
    return gender;
  }

  public void setGender(String gender) {
    this.gender = gender;
  }

  public void say() {
    System.out.println("Hello world!");
  }

  public String showInfo() {
    return "My name is " + this.name;
  }

}

public class ClassTest {

  public static void main(String[] args) {
    try {
      //先載入類,再建立例項,等同於People tim = new People();
      People tim = (People) Class.forName("com.tim.People").newInstance();
      tim.say();

      // 獲取tim這個物件的類描述資訊,
      // 可以獲取:類的構造方法,已經宣告的欄位、方法,獲取類或者方法的註解,獲取類的包名、父類,以及判斷類是否是陣列、是否是列舉、是否是介面
      // 主要針對不清楚類的內部資訊時,使用該方法獲取
      Class peopleClass = tim.getClass();
      Field[] peopleField = peopleClass.getDeclaredFields();//獲取類的欄位
      for (Field field : peopleField) {
        System.out.println(field.getName());
      }

    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }

}