<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在一個方法中將一個物件的參照傳遞給另外一個方法,參照指向的物件是同一個
public class Person { int age; String name; public Person(int age, String name) { this.age = age; this.name = name; } public static void main(String[] args) { Person p=new Person(18, "tom"); System.out.println("main: "+p); f(p); } public static void f(Person p) { System.out.println("f(): "+p); } }
參照別名
public static void main(String[] args) { Person p=new Person(18, "tom"); Person p2=p; p2.age++; System.out.println(p.age);//19 }
參照p和p2指向的是同一個物件,p2對物件的屬性進行操作,當使用參照p存取物件的屬性時當然也改變,同樣的情況也發生在物件參照在方法之間的傳遞,如下面的程式碼:
public static void main(String[] args) { Person p=new Person(18, "tom"); f(p); System.out.println(p.age);//19 } public static void f(Person p) { p.age++; }
幾個概念:
Java中方法之間只有值傳遞
傳遞基本型別時,傳遞的是基本型別的值的拷貝
public static void main(String[] args) { int a=100; change(a); System.out.println(a);//100 不受影響 } public static void change(int a) { a=99; }
傳遞物件時,傳遞的是物件的參照拷貝
public static void main(String[] args) { Person p=new Person(18, "tom"); f(p); System.out.println(p.age);//還是18 f()中p指向了一個新的物件 不影響main函數 } public static void f(Person p) { p=new Person(20, "bob"); }
傳遞物件時如果在另外一個方法中對物件的屬性進行操作會對main方法產生“副作用”, 但是如果只是簡單的對參照進行操作是沒有影響的
步驟:
類實現Cloneable空介面,預設情況下不希望所有的類都有克隆能力,當需要某個類有克隆能力時就需要實現該介面作為一種“可克隆”的標記,否則克隆時會報錯CloneNotSupportedException
public interface Cloneable { }
重寫clone方法,clone方法是Object類中的,它在Object類中的是一個protected的本地方法,需要重寫,加上public修飾符,否則只能在當前類中使用clone方法
protected native Object clone() throws CloneNotSupportedException;
public class Person implements Cloneable { int age; String name; public Person(int age, String name) { this.age = age; this.name = name; } public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } public static void main(String[] args) throws CloneNotSupportedException { Person p1=new Person(18, "tom"); Person p2=p1.clone(); System.out.println(p1+" name: "+p1.name+" age: "+p1.age); System.out.println(p2+" name: "+p2.name+" age: "+p2.age); } }
重寫clone方法時實際是就是呼叫Object類中的本地clone方法,Object類中的clone方法做了哪些工作?
Object類中clone方法負責建立正確大小的儲存空間,並執行了從原始物件中所有二進位制位到新物件記憶體中的按位元複製。
場景:Person類中增加一個參照型別的屬性Country, 表示這個人所屬的國家,然後進行克隆
package test; class Country{ String nation; public Country(String nation) { super(); this.nation = nation; } } public class Person implements Cloneable { int age; String name; Country country; public Person(int age, String name,Country country) { this.age = age; this.name = name; this.country=country; } public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } public static void main(String[] args) throws CloneNotSupportedException { Country country=new Country("China"); Person p1=new Person(18, "tom",country); Person p2=p1.clone(); System.out.println(p1+" name: "+p1.name+" age: "+p1.age+" country: "+p1.country); System.out.println(p2+" name: "+p2.name+" age: "+p2.age+" country: "+p2.country); p1.name="bob"; p1.country.nation="America"; System.out.println(p1+" name: "+p1.name+" age: "+p1.age+" country: "+p1.country.nation); System.out.println(p2+" name: "+p2.name+" age: "+p2.age+" country: "+p2.country.nation); } }
問題描述: 當Person類中有一個參照型別屬性時,對於基本型別資料和String型別是對值進行拷貝的,因此改變p1的name不影響p2的name, 但是對於Country這種參照型別,在clone時僅僅是拷貝了一份物件的參照,拷貝的參照和原來的參照指向的是同一個物件,因此p1改變country的屬性時,p2的country的屬性也發生了改變
解決淺拷貝問題的關鍵點在於不僅僅是拷貝參照,而且要拷貝一份參照指向的物件,深拷貝有兩種方式:
如果一個類A中有多個參照型別,那麼這些參照型別的類需要實現 Cloneable介面,在對A的物件進行克隆時,逐個淺拷貝其中的參照型別
eg: Person類中有Country參照型別,在進行clone時,單獨對country進行淺拷貝
package test; class Country implements Cloneable{ String nation; public Country(String nation) { super(); this.nation = nation; } public Country clone() throws CloneNotSupportedException { return (Country) super.clone(); } } public class Person implements Cloneable { int age; String name; Country country; public Person(int age, String name,Country country) { this.age = age; this.name = name; this.country=country; } public Person clone() throws CloneNotSupportedException { Person p=null; p=(Person) super.clone(); p.country=p.country.clone();//對country進行淺拷貝 return p; } public static void main(String[] args) throws CloneNotSupportedException { Country country=new Country("China"); Person p1=new Person(18, "tom",country); Person p2=p1.clone(); System.out.println(p1+" name: "+p1.name+" age: "+p1.age+" country: "+p1.country); System.out.println(p2+" name: "+p2.name+" age: "+p2.age+" country: "+p2.country); p1.name="bob"; p1.country.nation="America"; System.out.println(p1+" name: "+p1.name+" age: "+p1.age+" country: "+p1.country.nation); System.out.println(p2+" name: "+p2.name+" age: "+p2.age+" country: "+p2.country.nation); } }
package test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class Country implements Serializable{ private static final long serialVersionUID = 1L; String nation; public Country(String nation) { super(); this.nation = nation; } } public class Person implements Cloneable,Serializable { private static final long serialVersionUID = 1L; int age; String name; Country country; public Person(int age, String name,Country country) { this.age = age; this.name = name; this.country=country; } public Person clone() throws CloneNotSupportedException { Person p=null; ObjectInputStream ois=null; ObjectOutputStream oos=null; ByteArrayInputStream bais=null; ByteArrayOutputStream baos=null; try { baos=new ByteArrayOutputStream(); oos=new ObjectOutputStream(baos); oos.writeObject(this);//Person物件序列化 序列化寫入到baos流中 bais=new ByteArrayInputStream(baos.toByteArray()); ois=new ObjectInputStream(bais);//從baos流中讀取資料到ois p=(Person) ois.readObject();//ois讀取物件資料 } catch (Exception e) { e.printStackTrace(); }finally { if(bais!=null) try { bais.close(); } catch (IOException e) { e.printStackTrace(); } if(baos!=null) try { baos.close(); } catch (IOException e) { e.printStackTrace(); } if(oos!=null) try { oos.close(); } catch (IOException e) { e.printStackTrace(); } if(ois!=null) try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } return p; } public static void main(String[] args) throws CloneNotSupportedException { Country country=new Country("China"); Person p1=new Person(18, "tom",country); Person p2=p1.clone(); System.out.println(p1+" name: "+p1.name+" age: "+p1.age+" country: "+p1.country); System.out.println(p2+" name: "+p2.name+" age: "+p2.age+" country: "+p2.country); p1.name="bob"; p1.country.nation="America"; System.out.println(p1+" name: "+p1.name+" age: "+p1.age+" country: "+p1.country.nation); System.out.println(p2+" name: "+p2.name+" age: "+p2.age+" country: "+p2.country.nation); } }
總結: 實現一個可克隆的類的步驟
到此這篇關於Java物件傳遞與返回細節問題的文章就介紹到這了,更多相關Java物件傳遞與返回內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45