創建對象的四種方式


創建對象的四種方式

一:new運算的方式創建對象

首先我們有一個關於寵物的類Dog

 

當我們程序中需要出現一只狗狗的時候,我們就可以使用new來創建一個具體的對象了

 

在這里我們就通過了new的方式獲得了一個具體的對象,並且起名為小黑,年齡為3歲。

 

現在,dog1就帶表了堆中剛才所實例化出來的對象。以后我們要操作剛才new出來的對象就可以通過dog1來操作了,例如我們讓小狗打個招呼(調用Dog類的show方法):

 

二:通過反射的方式創建對象

Java的反射技術是java程序的特征之一,它允許運行中的Java程序對自身進行檢查,或者說“自審”,並能直接操作程序的內部屬性。

反射的作用:1)可以通過反射機制發現對象的類型,找到類中包含的方法、屬性和構造器2)可以通過反射創建對象並訪問任意對象方法和屬性

第二種創建java對象的方式就是通過反射來創建了。

還是我們之前用過的Dog類,首先JVM利用ClassLoader(類加載器)先將Dog類加載到內存,然后馬上產生了一個Class類型的對象,該對象可以看成是一個模型,以后無論創建多少個Dog類的實例都是利用該模型來生成(一個類所對應的Class類型的對象只有一個)。

通過反射創建對象第一步:需要獲得class對象

 

這樣獲取到類對象之后就可以通過newInstance()這個方法來獲取具體的對象了,需要注意的是這個方法的返回值是Object類型,我們需要進行轉型操作

 

這樣我們就通過反射的方式創建好了java對象,newInstance()和new的區別如下:

newInstance: 弱類型。低效率。只能調用無參構造。new: 強類型。相對高效。能調用任何public構造。

在這里需要注意的是,newInstance()這個方法只能夠調用無參的構造函數(其實這也符合javabean規范,一個類必須擁有一個無參構造函數),現在我們在Dog類中寫有參構造函數(默認覆蓋無參構造函數),值得注意的是,當我們寫了有參構造函數之后,系統將不再提供默認的無參構造函數,如果需要的話,需要你自己寫

 

現在再去調用newInstance()方法

 

現在程序運行結果為java.lang.InstantiationException,着就是程序沒有無參構造函數而使用newInstance()方法引發的錯誤了

當然如果你需要調用有參構造函數的話,可以通過以下的辦法:

 

程序的第二行我們調用Class對象的getConstructor方法,然后在參數列表中傳入String和int,因為我們的有參構造函數的參數列表就是這樣規定的,現在我們就獲取到了前邊定義好的Dog類的有參構造函數了第三行我們通過獲取的Constructor對象調用newInstance方法,然后在方法中傳入Object類型的參數列表,因為我們的有參構造函數需要這些值,這樣就可以通過反射的方式創建只有有參構造函數的對象了

三:通過對象反序列化的方式來創建

當我們使用反序列化一個對象的時候,JVM會給我們創建一個對象。但是,反序列化的時候JVM並不會去調用類的構造函數(前邊兩種方式都會去調用構造函數)來創建對象,而是通過之前序列化對象的字節序列來創建的。

序列化對象必須實現Serializable這個接口把對象轉為字節序列的過程稱為對象的序列化把字節序列恢復為對象的過程稱為對象的反序列化

 

需要注意的是:Dog類需要實現Serializable這個接口才可以被序列化/反序列化,否則會出現java.io.NotSerializableException異常

對象序列化通常有兩種用途:

1)將對象的字節序列永久的保存到硬盤上

例如web服務器把某些對象保存到硬盤讓他們離開內存空間,節約內存,當需要的時候再從硬盤上取回到內存中使用

2)在網絡上傳遞字節序列

當兩個進程進行遠程通訊的時候,發送方將java對象轉換成字節序列發送(序列化),接受方再把這些字節序列轉換成java對象(反序列化)

Dog類實現了Serializable接口后,我們現在將Dog對象序列化

 

通過ObjectOutputStream的writeObject方法,我們就將一個對象完成了序列化

現在我們再次將剛才序列化后的對象反序列化回來,這次用到的是ObjectInputStream的readObject方法:

 

這樣我們就使用了對象的序列化完成了java對象的創建

四:通過clone的方式來創建

clone方法來源於java中object類,在jdk中的解釋為:該方法返回一個此對象的副本。clone顧名思義就是復制的意思。所謂復制對象就是在內存中分配一個和原一模一樣的空間,在此創建新的對象。

我們現在就來完成clone的實驗,首先我們需要在需要clone的類中實現Cloneable接口,

否則會出現java.lang.CloneNotSupportedException異常,由於Object類中clone方法是protected 修飾的,所以我們必須在需要克隆的類中重寫克隆方法

 

現在進入實驗1:

 

返回值為true,因為在這個地方只有d1是真實創建了對象,d2來源於d1的賦值,引用地址值一樣(代表是同一個對象),所以==判斷結果為true

現在進入實驗2:

 

實驗結果為false,因為clone是真實在內存中重新划分一塊區域來存儲新的對象,d1和d2是兩個不同的對象所以返回結果值為false

這樣我們就使用了對象的克隆的方式完成了java對象的創建。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM