程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java中Class類工作原理詳解

Java中Class類工作原理詳解

編輯:關於JAVA

1.Class對象

Class對象包含了與類相關的信息。事實上,Class對象就是用來創建類的所有的“普通”對象的。

類是程序的一部分,每個類都有一個Class對象。換言之,每當編寫並且編譯了一個新類,就會產生一個Class對象(恰當地說,是被保存在一個同名的.class文件中)。在運行時,當我們想生成這個類的對象時,運行這個程序的Java虛擬機(JVM)首先檢查這個類的Class對象是否已經加載。如果尚未加載,JVM就會根據類名查找.class文件,並將其載入。

一旦某個類的Class對象被載入內存,它就被用來創建這個類的所有對象。看下面示例。

SweetShop.java

package com.zj.sample;
class Candy {
  static {
    System.out.println("Loading Candy");
  }
}
class Gum {
  static {
    System.out.println("Loading Gum");
  }
}
class Cookie {
  static {
    System.out.println("Loading Cookie");
  }
}
public class SweetShop {
  public static void main(String[] args) {
    System.out.println("inside main");
    new Candy();
    System.out.println("After creating Candy");
    try {
      Class.forName("com.zj.sample.Gum");
    } catch (ClassNotFoundException e) {
      System.out.println("Couldn't find Gum");
    }
    System.out.println("After Class.forName(\"Gum\")");
    new Cookie();
    System.out.println("After creating Cookie");
  }
}

結果:

inside main

Loading Candy

After creating Candy

Loading Gum

After Class.forName("Gum")

Loading Cookie

After creating Cookie

2.獲取Class實例的三種方式

1)利用對象調用getClass()方法獲取該對象的Class實例。

2)使用Class類的靜態方法forName(),用類的名字獲取一個Class實例。

3)運用.class的方式來獲取Class實例,對於基本數據類型的封裝類,還可以采用.TYPE來獲取相對應的基本數據類型的Class實例。

3.Class.forName

上面的示例中:

Class.forName("com.zj.sample.Gum");

這個方法是Class類(所有Class對象都屬於這個類)的一個static成員。Class對象就和其它對象一樣,我們可以獲取並操作它的引用。forName()是取得Class對象的引用的一種方法。它是用一個包含目標類的文本名的String作輸入參數,返回的是一個Class對象的引用。

4.類字面常量

Java還提供了另一種方法來生成對Class對象的引用,即使用“類字面常量”。對上述程序來說,可以是:

com.zj.sample.Gum.class;

5.關鍵字instanceof

關鍵字instanceof返回一個布爾值,判斷是不是某個特定類型的實例。

if(x instanceof Dog) ((Dog)x).bark();

6.獲取Class實例

package com.zj.sample;
class Point {
  int x, y;
}
class ClassTest {
  public static void main(String[] args) {
    Point pt = new Point();
    Class c1 = pt.getClass();
    System.out.println(c1.getName());
    try {
      Class c2 = Class.forName("com.zj.sample.Point");
      System.out.println(c2.getName());
    } catch (Exception e) {
      e.printStackTrace();
    }
    Class c3 = Point.class;
    System.out.println(c3.getName());
    Class c4 = int.class;
    System.out.println(c4.getName());
    Class c5 = Integer.TYPE;
    System.out.println(c5.getName());
    Class c6 = Integer.class;
    System.out.println(c6.getName());
  }
}

結果:

com.zj.sample.Point

com.zj.sample.Point

com.zj.sample.Point

int

int

java.lang.Integer

7.Class的其他方法

1)Class.newInstance()使用所選的Class對象生成該類的新實例。它調用了缺省(無參數)的類構造器生成新的對象。所以使用newInstance()創建的類必須有一個缺省構造器。對於newInstance()來說,可以在原先沒有任何對象存在的情況下,使用它創建一個新的對象。

利用newInstance()實例化一個對象:

package com.zj.sample;
class Point {
  static {
    System.out.println("Loading Point");
  }
  int x, y;
}
class ClassTest {
  public static void main(String[] args) {
    try {
      Class c = Class.forName("com.zj.sample.Point");
      Point pt = (Point) c.newInstance();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

結果:

Loading Point

2)Class.isInstance()方法提供了一種動態地調用instanceof運算符的途徑。

3)Class.getInterfaces()方法返回Class對象的數組,這些對象代表的是某個Class對象所包含的接口。

4)如果有一個Class對象,那麼就可以通過getSuperclass()獲取它的直接基類。這個方法自然也是返回一個Class引用,所以可以進一步查詢其基類。這意味著在運行時,可以找到一個對象完整的類層次結構。

5)Class類支持反射的概念,Java附帶的庫java.lang.reflect包含了Field、Method以及Constructor類(每個類都實現了Member接口)。這些類型的對象是由JVM在運行時創建的,用以表示未知類裡對應的成員。這樣可以使用Constructor創建新的對象,用get()和set()方法讀取和修改與Field對象關聯的字段,用invoke()方法調用與Method對象關聯的方法。另外,還可以調用getFields()、getMethods、getConstrucotrs()方法,返回表示字段、方法以及構造器的對象的數組。

8.利用反射API察看未知類的構造方法與方法

package com.zj.sample;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
class Point {
  static {
    System.out.println("Loading Point");
  }
  int x, y;
  void output() {
    System.out.println("x=" + x + "," + "y=" + y);
  }
  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }
}
class ClassTest {
  public static void main(String[] args) {
   
    try {
      Class c = Class.forName("com.zj.sample.Point");
      Constructor[] cons = c.getDeclaredConstructors();
      for (int i = 0; i < cons.length; i++)// 返回所有聲明的構造方法
      {
       System.out.println(cons[i]);
      }
      Method[] ms = c.getDeclaredMethods();
      for (int i = 0; i < ms.length; i++)// 返回所有聲明的方法
      {
       System.out.println(ms[i]);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

結果:

Loading Point

com.zj.sample.Point(int,int)

void com.zj.sample.Point.output()

9.動態調用一個類的實例(完全沒有出現point這個名字)

package com.zj.sample;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
class Point {
  static {
    System.out.println("Loading Point");
  }
  int x, y;
  void output() {
    System.out.println("x=" + x + "," + "y=" + y);
  }
  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }
}
class ClassTest {
  public static void main(String[] args) {
   
    try {
      Class c = Class.forName("com.zj.sample.Point");
      Constructor[] cons = c.getDeclaredConstructors();
      Class[] params = cons[0].getParameterTypes();// 察看構造器的參數信息
      Object[] paramValues = new Object[params.length];// 構建數組傳遞參數
      for (int i = 0; i < params.length; i++) {
       if (params[i].isPrimitive())// 判斷class對象表示是否是基本數據類型
       {
         paramValues[i] = new Integer(i);
       }
      }
      Object o = cons[0].newInstance(paramValues);// 創建一個對象的實例
      Method[] ms = c.getDeclaredMethods();// 調用方法
      ms[0].invoke(o, null);// 用指定的參數調用(output方法沒有參數,null)
    } catch (Exception e) {
      e.printStackTrace();
    }
 }
}

結果:

Loading Point

x=0,y=1

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved