1. 程式人生 > >JAVA中類、例項與Class物件

JAVA中類、例項與Class物件

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

 

例項

簡單理解,就是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的目錄下)

package com.dxjia.sample;

public class Name {
    static int count = 0;
    static {
        count++;
        System.out.println("Name Class Loaded! count = [" + count + "]" );
    }

    public Name() {
        System.out.println("Name Constructor called!");
    }

}

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

import com.dxjia.sample.Name;

public class Test {
    static {
        Name mName;
        System.out.println("Test Class loaded");
    }
    
    public  static void main(String[] args) {
        System.out.println("entern Test main()");
        
        // Name.class
        Class mClassPointClass;
        // Class.forName("完整包名+類名")
        Class mClassForName;
        // new 物件後,物件.getClass()
        Class mClassObjectPointClass1;
        Class mClassObjectPointClass2;

        try {
            //測試 類名.class
            mClassPointClass = Name.class;
            System.out.println("mClassPointClass = " + mClassPointClass);
            
            //測試Class.forName()
            mClassForName = Class.forName("com.dxjia.sample.Name");
            System.out.println("mClassForName = " + mClassForName);

            //測試Object.getClass()
            Name name1 = new Name();
            mClassObjectPointClass1 = name1.getClass();
            System.out.println("mClassObjectPointClass1 = " + mClassObjectPointClass1);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block 
            e.printStackTrace();
            return;
        } 

        Name name2;
        System.out.println("defined one Name object");
        name2 = new Name();
        System.out.println("Name object instance done!");
        
        mClassObjectPointClass2 = name2.getClass();
        
        if (mClassForName == mClassPointClass
            && mClassPointClass == mClassObjectPointClass1
            && mClassObjectPointClass1 == mClassObjectPointClass2) {
            System.out.println("all the Class object equal...");
        }
    }
}

分別對他們進行編譯:
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物件的生成方式如下:

1.類名.class 說明: JVM將使用類裝載器, 將類裝入記憶體(前提是:類還沒有裝入記憶體),不做類的初始化工作.返回Class的物件

2.Class.forName("類名字串") (注:類名字串是包名+類名) 說明:裝入類,並做類的靜態初始化,返回Class的物件

3.例項物件.getClass() 說明:對類進行靜態初始化、非靜態初始化;返回引用執行時真正所指的物件(因為:子物件的引用可能會賦給父物件的引用變數中)所屬的類的Class的物件


Class物件其實就是 ClassLoader 類載入器生成的,在 JVM 中,一個類有且只有一個 Class 物件

轉載至:https://www.cnblogs.com/flyme/p/4571030.html