JAVA中類、實例與Class對象

from:https://www.cnblogs.com/flyme/p/4571030.html

      類是面向對象編程語言的一個重要概念,它是對一項事物的抽象概括,可以包含該事物的一些屬性定義,以及操作屬性的方法。面向對象編程中,我們都是以類來編碼。

 

實例

簡單理解,就是new,就是對類的實例化,創建這個類對應的實際對象,類只是對事物的描述,而實例化就相當於爲這個描述新開闢了一塊內存,可以改變這塊區域裏的各種屬性(成員變量),當然,也可以實例化多塊區域,只是不同的對象而已。

 

Class

注意這裏C大寫了,與類概念區分開,在java裏,Class是一個實實在在的類,在包 java.lang 下,有這樣一個Class.java文件,它跟我們自己定義的類一樣,是一個實實在在的類,Class對象就是這個Class類的實例了。在Java裏,所有的類的根源都是Object類,而Class也不例外,它是繼承自Object的一個特殊的類,它內部可以記錄類的成員、接口等信息,也就是在Java裏,Class是一個用來表示類的類。(o(∩_∩)o 有點繞啊,抓住關鍵一點,Class是一個實實在在的類,可以爲它創建實例,也就是本文後面提到的Class對象,也看叫做Class實例)。

  java提供了下面幾種獲取到類的Class對象的方法:

    1) 利用對象實例調用getClass()方法獲取該對象的Class實例;
        2) 使用Class類的靜態方法forName("包名+類名"),用類的名字獲取一個Class實例

        3)運用 類名.class 的方式來獲取Class實例;

 

  我們知道java世界是運行在JVM之上的,我們編寫的類代碼,在經過編譯器編譯之後,會爲每個類生成對應的.class文件,這個就是JVM可以加載執行的字節碼。運行時期間,當我們需要實例化任何一個類時,JVM會首先嚐試看看在內存中是否有這個類,如果有,那麼會直接創建類實例;如果沒有,那麼就會根據類名去加載這個類,當加載一個類,或者當加載器(class loader)的defineClass()被JVM調用,便會爲這個類產生一個Class對象(一個Class類的實例),用來表達這個類,該類的所有實例都共同擁有着這個Class對象,而且是唯一的。

 

總結

  在java裏,類只是信息描述的,寫明瞭有哪些內部屬性及接口,你可以理解爲是定義了一套規則;而Class對象在java裏被用來對類的情況進行表述的一個實例,也就是是類的實際表徵,可以理解爲是對規則的圖表化,這樣JVM才能直觀的看懂,可以看做是一個模版;而類的實例化對象,就是通過模版,開闢出的一塊內存進行實際的使用。

 

例子:

我們通過一個例子來理解Class實例,爲了說明方便,我們新建一個包名深點的類。

新建Name.java(當然,該文件要放在com\dxjia\sample的目錄下)

複製代碼
 1 package com.dxjia.sample;
 2 
 3 public class Name {
 4     static int count = 0;
 5     static {
 6         count++;
 7         System.out.println("Name Class Loaded! count = [" + count + "]" );
 8     }
 9 
10     public Name() {
11         System.out.println("Name Constructor called!");
12     }
13 
14 }
複製代碼

 

再在根目錄新建一個Test主類

複製代碼
 1 import com.dxjia.sample.Name;
 2 
 3 public class Test {
 4     static {
 5         Name mName;
 6         System.out.println("Test Class loaded");
 7     }
 8     
 9     public  static void main(String[] args) {
10         System.out.println("entern Test main()");
11         
12         // Name.class
13         Class mClassPointClass;
14         // Class.forName("完整包名+類名")
15         Class mClassForName;
16         // new 對象後,對象.getClass()
17         Class mClassObjectPointClass1;
18         Class mClassObjectPointClass2;
19 
20         try {
21             //測試 類名.class
22             mClassPointClass = Name.class;
23             System.out.println("mClassPointClass = " + mClassPointClass);
24             
25             //測試Class.forName()
26             mClassForName = Class.forName("com.dxjia.sample.Name");
27             System.out.println("mClassForName = " + mClassForName);
28 
29             //測試Object.getClass()
30             Name name1 = new Name();
31             mClassObjectPointClass1 = name1.getClass();
32             System.out.println("mClassObjectPointClass1 = " + mClassObjectPointClass1);
33         } catch (ClassNotFoundException e) {
34             // TODO Auto-generated catch block 
35             e.printStackTrace();
36             return;
37         } 
38 
39         Name name2;
40         System.out.println("defined one Name object");
41         name2 = new Name();
42         System.out.println("Name object instance done!");
43         
44         mClassObjectPointClass2 = name2.getClass();
45         
46         if (mClassForName == mClassPointClass
47             && mClassPointClass == mClassObjectPointClass1
48             && mClassObjectPointClass1 == mClassObjectPointClass2) {
49             System.out.println("all the Class object equal...");
50         }
51     }
52 }
複製代碼

分別對他們進行編譯:

1 javac com\dxjia\sample\Name.java
2 javac Test.java

執行:

1 java Test

 

代碼中使用了static靜態代碼塊來進行實驗,一個類的運行,JVM做會以下幾件事情 1、類裝載 2、鏈接 3、初始化 4、實例化;而初始化階段做的事情是初始化靜態變量和執行靜態方法等的工作,而且永遠只執行一次。

輸出結果:

Test Class loaded
entern Test main()
mClassPointClass = class com.dxjia.sample.Name
Name Class Loaded! count = [1]
mClassForName = class com.dxjia.sample.Name
Name Constructor called!
mClassObjectPointClass1 = class com.dxjia.sample.Name
defined one Name object
Name Constructor called!
Name object instance done!
all the Class object equal...

 

通過結果可以看出在使用 類名.class獲得Class實例時,並不會觸發類的初始化,而 Class.forName方法就會觸發,當然實例化對象肯定也是會觸發的,但因爲static代碼塊只執行一次,所以不會再有打印,最後的打印,說明一個類的Class實例只有唯一的一個。

 

擴展:

對於Class.forName("")方法,可以看看下面這篇文章,結合起來理解,會更清晰:理解Class.forName()

發佈了28 篇原創文章 · 獲贊 29 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章