簡單了解JAVA中類、實(shí)例與Class對(duì)象
類
類是面向?qū)ο缶幊陶Z言的一個(gè)重要概念,它是對(duì)一項(xiàng)事物的抽象概括,可以包含該事物的一些屬性定義,以及操作屬性的方法。面向?qū)ο缶幊讨?,我們都是以類來編碼。
實(shí)例
簡單理解,就是new,就是對(duì)類的實(shí)例化,創(chuàng)建這個(gè)類對(duì)應(yīng)的實(shí)際對(duì)象,類只是對(duì)事物的描述,而實(shí)例化就相當(dāng)于為這個(gè)描述新開辟了一塊內(nèi)存,可以改變這塊區(qū)域里的各種屬性(成員變量),當(dāng)然,也可以實(shí)例化多塊區(qū)域,只是不同的對(duì)象而已。
Class
注意這里C大寫了,與類概念區(qū)分開,在java里,Class是一個(gè)實(shí)實(shí)在在的類,在包 java.lang 下,有這樣一個(gè)Class.java文件,它跟我們自己定義的類一樣,是一個(gè)實(shí)實(shí)在在的類,Class對(duì)象就是這個(gè)Class類的實(shí)例了。
在Java里,所有的類的根源都是Object類,而Class也不例外,它是繼承自O(shè)bject的一個(gè)特殊的類,它內(nèi)部可以記錄類的成員、接口等信息,也就是在Java里,Class是一個(gè)用來表示類的類。(o(∩_∩)o 有點(diǎn)繞啊,抓住關(guān)鍵一點(diǎn),Class是一個(gè)實(shí)實(shí)在在的類,可以為它創(chuàng)建實(shí)例,也就是本文后面提到的Class對(duì)象,也看叫做Class實(shí)例)。
java提供了下面幾種獲取到類的Class對(duì)象的方法:
1) 利用對(duì)象實(shí)例調(diào)用getClass()方法獲取該對(duì)象的Class實(shí)例;
2) 使用Class類的靜態(tài)方法forName("包名+類名"),用類的名字獲取一個(gè)Class實(shí)例
3)運(yùn)用 類名.class 的方式來獲取Class實(shí)例;
我們知道java世界是運(yùn)行在JVM之上的,我們編寫的類代碼,在經(jīng)過編譯器編譯之后,會(huì)為每個(gè)類生成對(duì)應(yīng)的.class文件,這個(gè)就是JVM可以加載執(zhí)行的字節(jié)碼。運(yùn)行時(shí)期間,當(dāng)我們需要實(shí)例化任何一個(gè)類時(shí),JVM會(huì)首先嘗試看看在內(nèi)存中是否有這個(gè)類,如果有,那么會(huì)直接創(chuàng)建類實(shí)例;如果沒有,那么就會(huì)根據(jù)類名去加載這個(gè)類,當(dāng)加載一個(gè)類,或者當(dāng)加載器(class loader)的defineClass()被JVM調(diào)用,便會(huì)為這個(gè)類產(chǎn)生一個(gè)Class對(duì)象(一個(gè)Class類的實(shí)例),用來表達(dá)這個(gè)類,該類的所有實(shí)例都共同擁有著這個(gè)Class對(duì)象,而且是唯一的。
總結(jié)
在java里,類只是信息描述的,寫明了有哪些內(nèi)部屬性及接口,你可以理解為是定義了一套規(guī)則;而Class對(duì)象在java里被用來對(duì)類的情況進(jìn)行表述的一個(gè)實(shí)例,也就是是類的實(shí)際表征,可以理解為是對(duì)規(guī)則的圖表化,這樣JVM才能直觀的看懂,可以看做是一個(gè)模版;而類的實(shí)例化對(duì)象,就是通過模版,開辟出的一塊內(nèi)存進(jìn)行實(shí)際的使用。
例子:
我們通過一個(gè)例子來理解Class實(shí)例,為了說明方便,我們新建一個(gè)包名深點(diǎn)的類。
新建Name.java(當(dāng)然,該文件要放在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!"); } }
再在根目錄新建一個(gè)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 對(duì)象后,對(duì)象.getClass() Class mClassObjectPointClass1; Class mClassObjectPointClass2; try { //測(cè)試 類名.class mClassPointClass = Name.class; System.out.println("mClassPointClass = " + mClassPointClass); //測(cè)試Class.forName() mClassForName = Class.forName("com.dxjia.sample.Name"); System.out.println("mClassForName = " + mClassForName); //測(cè)試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..."); } } }
分別對(duì)他們進(jìn)行編譯:
javac com\dxjia\sample\Name.java javac Test.java
執(zhí)行:
java Test
代碼中使用了static靜態(tài)代碼塊來進(jìn)行實(shí)驗(yàn),一個(gè)類的運(yùn)行,JVM做會(huì)以下幾件事情 1、類裝載 2、鏈接 3、初始化 4、實(shí)例化;而初始化階段做的事情是初始化靜態(tài)變量和執(zhí)行靜態(tài)方法等的工作,而且永遠(yuǎn)只執(zhí)行一次。
輸出結(jié)果:
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...
通過結(jié)果可以看出在使用 類名.class獲得Class實(shí)例時(shí),并不會(huì)觸發(fā)類的初始化,而 Class.forName方法就會(huì)觸發(fā),當(dāng)然實(shí)例化對(duì)象肯定也是會(huì)觸發(fā)的,但因?yàn)閟tatic代碼塊只執(zhí)行一次,所以不會(huì)再有打印,最后的打印,說明一個(gè)類的Class實(shí)例只有唯一的一個(gè)。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java中List、Set、Map的區(qū)別和實(shí)現(xiàn)方式示例代碼
這篇文章主要介紹了Java中List、Set、Map的區(qū)別和實(shí)現(xiàn)方式示例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06使用redis的increment()方法實(shí)現(xiàn)計(jì)數(shù)器功能案例
這篇文章主要介紹了使用redis的increment()方法實(shí)現(xiàn)計(jì)數(shù)器功能案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11詳解PipedInputStream和PipedOutputStream_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了管道PipedInputStream和PipedOutputStream,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05IDEA打開項(xiàng)目所有東西都在報(bào)紅報(bào)錯(cuò)的解決方案
這篇文章主要給大家介紹了關(guān)于IDEA打開項(xiàng)目所有東西都在報(bào)紅報(bào)錯(cuò)的三個(gè)解決方案,文中通過圖文介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用idea具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-06-06基于springboot實(shí)現(xiàn)整合shiro實(shí)現(xiàn)登錄認(rèn)證以及授權(quán)過程解析
這篇文章主要介紹了基于springboot實(shí)現(xiàn)整合shiro實(shí)現(xiàn)登錄認(rèn)證以及授權(quán)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12詳解Java編寫并運(yùn)行spark應(yīng)用程序的方法
這篇文章主要介紹了詳解Java編寫并運(yùn)行spark應(yīng)用程序的方法,內(nèi)容詳細(xì),結(jié)合了作者實(shí)際工作中的問題進(jìn)行具體分析,具有一定參考價(jià)值。2017-09-09springmvc 獲取@Requestbody轉(zhuǎn)換的異常處理方式
這篇文章主要介紹了springmvc 獲取@Requestbody轉(zhuǎn)換的異常處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07