1.對(duì)象的復(fù)制
???
String str1 = "This is a string!"? //這里是 "對(duì)象引用" 的復(fù)制
String str2 = new String(str1);? //這里是 "對(duì)象實(shí)例" 的復(fù)制
淺復(fù)制: 只復(fù)制復(fù)合對(duì)象本身.
深復(fù)制: 除了復(fù)制復(fù)合對(duì)象本身, 還復(fù)制了復(fù)合對(duì)象的引用的對(duì)象實(shí)例.
例如:
class Pupil{
??? public Pupil(String sno, String name, int age){
??????? this.sno = new String(sno);
??????? this.name = new String(name);
??????? this.age = age;
??? }
??? public String getSno() {
??????? return sno;
??? }
??? public String getName() {
??????? return name;
??? }
??? public int getAge() {
??????? return age;
??? }
??? public void setAge(int age) {
??????? this.age = age;
??? }
??? private String sno;
??? private String name;
??? private int age;
}
public class CopyDemo {
??? public static Pupil[] shallowCopy(Pupil[] aClass) {
??????? Pupil[] newClass = new Pupil[aClass.length];
??????? //此時(shí)newClass 與aClass 指向同一塊內(nèi)存
??????? for(int i=0; i<aClass.length; i++)
??????????? newClass[i] = aClass[i];
??????? return newClass;
??? }
????
??? public static Pupil[] deepCopy(Pupil[] aClass) {
??????? Pupil[] newClass = new Pupil[aClass.length];
??????? //此時(shí)newClass 與aClass 的相應(yīng)sno , name 指向同一塊內(nèi)存
??????? for(int i=0; i<aClass.length; i++) {
??????????? String sno = aClass[i].getSno();
??????????? String name = aClass[i].getName();
??????????? int age = aClass[i].getAge();
??????????? newClass[i] = new Pupil(sno, name, age);
??????? }
??????? return newClass;
??? }
??? public static Pupil[] deeperCopy(Pupil[] aClass) {
??????? Pupil[] newClass = new Pupil[aClass.length];
??????? //完全的復(fù)制
??????? for(int i=0; i<aClass.length; i++) {
??????????? String sno = new String(aClass[i].getSno());
??????????? String name = new String(aClass[i].getName());
??????????? int age = aClass[i].getAge();
??????????? newClass[i] = new Pupil(sno, name, age);
??????? }
??????? return newClass;
??? }
}
2.clone()的使用
* Object.clone()
* Cloneable 接口
* CloneNotSupportedException
a. 使用Object.clone 進(jìn)行復(fù)制
兩個(gè)必須條件:
1.一定要將重定義后的clone() 方法定義為公有方法(在Object 類中, 它是受保護(hù)的成員,??? 不能直接使用)
2.該后代類聲明實(shí)現(xiàn)接口 Cloneable 接口(當(dāng)類實(shí)現(xiàn)該接口, 其任何子類也會(huì)繼承該接口), 該接口實(shí)際上沒有任何
? 內(nèi)容, 只是一個(gè)標(biāo)識(shí), 標(biāo)志實(shí)現(xiàn)該接口的類提供clone() 方法.(這是接口的一種非典型用法)
public class Fraction implements Cloneable {
??? public Object clone() {
??????? try{
??????????? return super.clone();? //call protected method
??????? } catch (CloneNotSupportedException e) {
??????????? return null;
??????? }
??? }
??? //other methods ...
}
b.重寫Object.clone()
例如對(duì)?? private char[] cb; character buffer 進(jìn)行復(fù)制
?
// add in class Cirbuf
??????? public Object clone() {
??????? try{
??????????? Cirbuf copy = (Cirbuf)super.clone();
??????????? copy.cb = (char[])cb.clone();
??????????? return copy;
??????? }catch (CloneNotSupportedException e){
??????????? throw new InternalError(e.toString());
??????? }
??? }
c.復(fù)制數(shù)組
? 數(shù)組是在方法調(diào)用重以引用的形式傳遞的對(duì)象. 下述情況下非常適合引用來傳遞數(shù)組:
? *正在接收的方法不修改數(shù)組
? *正在調(diào)用的方法不必關(guān)心是否修改數(shù)組
? *正在調(diào)用的方法想要得到數(shù)組中的修改結(jié)果
? 否則, 就應(yīng)該在方法調(diào)用中傳遞數(shù)組對(duì)象的副本. 只需調(diào)用 arrObj.clone() 方法即可完成數(shù)組arrObj 的復(fù)制操作. 隨后將該數(shù)組副本強(qiáng)制轉(zhuǎn)換為其正確類型:
????? (type[])arrObj.clone();
?? System.arraycopy 方法提供一種用于在數(shù)組間復(fù)制多個(gè)元素的有效方式.
??????? System.arraycopy(source, i, target, j, len)
3.對(duì)象實(shí)例的比較
例如:
??? Pupil p1 = new Pupil("99184001", "zhang3", 18);
??? Pupil p2 = new Pupil("99184001", "zhang3", 18);
a. "=="
?? if(p1 == p2)...
? 此次測試的是對(duì)象引用, 其結(jié)果肯定是false, 只要兩個(gè)對(duì)象引用不是互為別名就不會(huì)相等.
b. 淺比較? false
?? if(p1.getSno() == p2.getSno() && p1.getName() == p2.getName()
???? && p1.getAge() == p2.getAge()) ...;
c. 深比較?? true[/code]??
? if(p1.getSno().equals(p2.getSno()) && p1.getName().equals(p2.getName())
???? && p1.getAge() == p2.getAge()) ...;[/code]
??? JAVA API 的跟類Object 也提供了equals() 方法, 但它只是比較兩個(gè)對(duì)象引用, 而非比較兩個(gè)對(duì)象實(shí)例.
??? 不管怎樣, 如果需要比較Pupil 類的對(duì)象(例如要將它們放入對(duì)象容器), 應(yīng)該為Pupil 類重定義equals() 方法:
???
??? public boolean equals(Object otherobj) {
??????? //檢查otherobj 是否為空
??????? if(otherobj == null) return false;
??????? //檢查otherobj 是否就是當(dāng)前對(duì)象
??????? if(otherobj == this) return true;
??????? //檢查otherobj 是否具有正確的類型, 即檢查是否可與當(dāng)前對(duì)象比較
??????? if(!(otherobj instanceof Pupil)) return false;
??????? //將otherobj 轉(zhuǎn)換為Pupil 類的對(duì)象引用
??????? Pupil tmpObj = (Pupil)otherobj;
??????? //關(guān)于學(xué)生是否相等的邏輯檢查
??????? if(sno.equals(tmpObj.sno) && name.equals(tmpObj.name)
???????????? && age == tmpObj.age) return true;
????????
??????? return false;
??? }
?? JAVA API 所提供的每個(gè)類幾乎都提供了采用深比較策略的equals() 方法, 例如String 類equals() 方法. 一般來說, 用戶自己定義的類也應(yīng)當(dāng)提供合適的equals() 方法, 特別是當(dāng)程序要將其對(duì)象放入JAVA API 所提供的對(duì)象容器類的時(shí)候.?
?? 按照約定, 任何類所提供的equals() 方法所實(shí)現(xiàn)的相等比較應(yīng)該是等價(jià)關(guān)系, 即滿足自反性, 對(duì)稱性和傳遞性. 另外一個(gè)類重定義了equals() 方法, 也應(yīng)該重定義相應(yīng)hashCode() 方法, 否則將這個(gè)類的對(duì)象放入映射對(duì)象容器時(shí)也會(huì)發(fā)生以外.