菜雞的Java課筆記 第十六 引用傳遞
referenceDelivery
引用傳遞是整個java 的精髓,也是所有初學者最難學的地方
引用的本質:同一塊堆記憶體可以被不同的棧記憶體所指向
下面通過三道程式來進行引用傳遞分析
範例:第一道引用範例
class Demo{ private int num = 10: public Demo(int num){ this.num = num: }public void setNum(int num){ this.num = num: } public int getNum(){ return this.num: } } public class referenceDelivery{ public static void main(String args[]){ Demo demo = new Demo(100): fun(demo): // Demo temp = demo System.out.println(demo.getNum()): }public static void fun(Demo temp){ temp.setNum(30): } } // 結果: 30
範例:第二道引用傳遞
public class referenceDelivery{ public static void main(String args[]){ String str = "hello": fun(str): System.out.println(str): } public static void fun(String temp){ temp= "world": } } // 結果: hello
字串一旦宣告則不可改變,字串物件內容的改變依靠的是引用的改變實現的
如果覺得以上的程式碼看起來很麻煩,那麼不如換一個思路:不要把String當成引用型別,而只當成基本資料型別
public class referenceDelivery{ public static void main(String args[]){ int str = 10: fun(str): System.out.println(str): } public static void fun(int temp){ temp = 30: } } //結果:10
範例:第三道引用傳遞
class Demo{ private String msg = "Hello": public Demo(String msg){ this.msg = msg: } public void setMsg(String msg){ this.msg = msg: } public String getMsg(){ rrturn this.msg: } } public class referenceDelivery{ public static void main(String args[]){ Demo demo = new Demo ("world"): fun(demo): System.out.println(demo.getMsg()): } public static void fun(String temp){ temp.setMsg("MLDN"): } } //結果: MLDN
引用傳遞一定要耐心使用記憶體分析,String這種型別額資料需要特殊處理
*/
/* Object comparison 物件比較
物件比較的實現以及引用的操作
所謂的物件比較指的就是可以判斷兩個物件是否相等
實際上現在物件是否相同只能夠依靠地址是否相同但是有些時候可能會出現地址不相同
但是內容相同的的情況,就好比String類的“==”與“equals()”的關係
那麼我們希望可以實現一個屬性自己的物件比較操作
然而要進行物件比較操作那麼首先要做的事情就是必須將兩個物件中的每個屬性內容分別比較
如果屬性內容全部相同那麼就表示同一個物件,否則就認為不是同一個物件
範例:物件比較的基礎實現
class Person{ private String name: private int age: public Person (String name,int age){ this.name: this.age|: } public String getName(){ rrturn this.name: } public int getAge(){ rrturn .this,age: } } public class referenceDelivery{ public static void main(String args[]){ Person perA = new Person("張三",20): Person perB = new Person("李四",20): if(perA.getName(),equals(perB,getName())&&perA,getAge()==perB.getAge()){ System.out.println("是同一個人"): }else{ System.out.println("不是同一個人"): } } //結果: 不是同一個人
現在的功能已經實現了,但是不能夠僅僅只是控制在實現的範疇,需要更好的實現,那麼以上的程式碼有什麼問題
直接的反映就是程式碼寫在主方法裡面那麼如果不寫在主方法裡面該寫在哪
class Person{ private String name: private int age: public Person (String name,int age){ this.name: this.age|: } public String getName(){ rrturn this.name: } public int getAge(){ rrturn .this,age: } // 此時需要接收一個要比較的物件(物件的本質就是資料的集合) // 同時在本類方法裡面還有一個隱藏的物件:this // 此時的compare()方法接收了自己本類的引用 // 由於此時的person引數物件在Person類中了,所以可以直接訪問私有屬性 public boolean compare(Person person){ if(person == null){// 就不要比較了 rrturn false: } if(this == person){ // 防止自己與自己比較,地址比較 rrturn true: } if(this.name.equals(person,name)&&this.age == person.age){ rrturn true: } rrturn false: } } public class referenceDelivery{ public static void main(String args[]){ Person perA = new Person("張三",20): Person perB = new Person("李四",20): if(perA.compare(perB)){ System.out.println("是同一個人"): }else{ System.out.println("不是同一個人"): } }
物件比較更多的是在分析層次上使用,而在實際之中,只有String用的比較多
物件比較一定是一個類自己具備的功能,所以一定要在類中寫一個比較方法
進行物件比較時一定是將物件中的每一個屬性進行逐步判斷,所有屬性都相同了,就表示物件是相同的,相等的
*/
/* 引用傳遞例項分析
將程式與生活聯絡在一起
一直以來一直強調:程式是生活的濃縮。生活的抽象,也就是說日常中的一切概念都可以通過程式來進行描述
下面描述這樣的一個程式:一個人有一輛車
在描述以上概念之前希望可以有一個對比,如果說現在你進行資料庫的設計,要描述以上的操作形式,你的資料表該如何設計呢?
CREATE TABLE person(
pid NUMBER,
name VARCHAR2(50),
CONSTRAINT pk_pid PRIMARY KEY(pid)
);
CREATE TABLE car(
pid NUMBER,
cname VARCHAR2(50),
CONSTRAINT pk_pid PRIMARY KEY(pid),
COMSTRAINT fk_pid2 FOREIGN KEY(pid)REFERENCES person(pid)
)
如果說現在要是進行類的設計,也需要兩個類:Person Car,那麼就可以發現兩者的關聯:
表名稱 = 類名稱:
表的欄位 = 類屬性
表的一行記錄 = 一個例項化物件
表的多行記錄 = 物件陣列
標的外來鍵 = 引用設定
正是因為有這樣的匹配關係,所以在實際的開發過程之中,簡單JAVA類不是憑空設計的,往往都與資料表的結構一一對應
範例:定義類
class Person{ private int pid: private String name: // car 為null了表示這個人沒有車 private Car car: // 一個人有一輛車 public Person(int pid,String name){ this.pid = pid: this.name = name: } public String getPersonlnfo(){ return"身份號:"+this.pid+",姓名:"+this.name: } public void setCar(Car car){ this.car = car: } public Car getCar(){ return this.car; } } class Car{ private String cname; // 如果人有車了,那麼必須同時修改車與人對的關係 private Person person; // 一輛車屬於一個人 public Car(String cname){ this.cname = cname: } public void setPerson(Person person){ this.person = person: } public Person getPerson(){ return this.person: } public String getCarlofo(){ return "汽車名稱:"+this.cname: } } public class biji{ public static void main(String args[]){ // 第一步:根據已有的結構設定內容 Person per = new Person(450802,"少爺"): Catr car = new Car("保時捷356A"): per,setCar(car): // 現在人有車了 car.setPerson(per): // 現在車屬於一個人了 // 第二步:根據關係取出資料 System.out.println(per,getPersonlnfo()): System.out.println(per,getCar().per,getCarlnfo()): // 程式碼鏈 System.out.println(car.getPerson().getPersonlnfo()): } } /* 結果: 身份號:450802,姓名:少爺 汽車名稱:保時捷356A 身份號:450802,姓名:少爺 */
此時程式中使用了自定義的資料型別,Person Car都是類。那麼隨後的操作主要是進行程式碼的測試
但是測試分為兩步:第一步設定內容,第二步取出內容
程式碼鏈別看單詞,就看每一個方法的返回值是什麼東西。如果是一個類的物件則可以繼續呼叫該類的方法
那麼也可以針對於此程式碼進行進一步額擴充套件。每個人還有孩子,每個孩子也可能有車
實際上這裡面需要注意的是每一個人的孩子一定還是人,並且具備有跟人同樣的屬性資訊,那麼就可以在Person裡面設計一個孩子的屬性
class Person{ private int pid: private String name: private Person child: //孩子 // car 為null了表示這個人沒有車 private Car car: // 一個人有一輛車 public Person(int pid,String name){ this.pid = pid: this.name = name: } public void setChild(Person child){ this.child = child: } public Person getChild(){ return this.child } public String getPersonlnfo(){ return"身份號:"+this.pid+",姓名:"+this.name: } public void setCar(Car car){ this.car = car: } public Car getCar(){ return this.car; } } class Car{ private String cname; // 如果人有車了,那麼必須同時修改車與人對的關係 private Person person; // 一輛車屬於一個人 public Car(String cname){ this.cname = cname: } public void setPerson(Person person){ this.person = person: } public Person getPerson(){ return this.person: } public String getCarlnfo(){ return "汽車名稱:"+this.cname: } } public class biji{ public static void main(String args[]){ // 第一步:根據已有的結構設定內容 Person per = new Person(450802,"少爺"): Person chd = new Person(450803,"小少爺"): // 有了孩子 Catr car = new Car("保時捷356A"): Car c = new Car("布加迪威龍銀河版"): per,setCar(car): // 現在人有車了 car.setPerson(per): // 現在車屬於一個人了 per.setChild(chd): // 一個人有一個孩子 chd.setCar(c): // 孩子有車 // 第二步:根據關係取出資料 System.out.println(per.getChild().getPersonlnfo()): // 通過父親的車找到父親的資訊,再找到父親的孩子的車的資訊 System.out.println(car.getPerson().getChild().getCar().getCarlnfo): } }
結果: 身份號:450803,姓名:小少爺
汽車名稱:布加迪威龍銀河版
引用的關係可以描述出不同類之間的引用關係
在現實的生活中這樣的設計實際上並不麻煩了,理論上任何的事物都可以進行這樣的整合
範例:抽象出衣服
class 袖子{}
class 衣領{}
class 衣服{
private 袖子 左:
private 袖子 右:
private 衣領 物件:
}
範例:抽象電腦
class cpu{}
class 記憶體{}
class 顯示卡{}
class 硬碟{}
class 主機板{
private CPU 物件 :
private 記憶體 物件[]:
private 硬碟 物件[]:
private 顯示卡 物件:
}
class 鍵盤{}
class 滑鼠{}
class 主機{
private 主機板 物件:
private 滑鼠 物件;
private 鍵盤 物件:
}
此處也同樣屬於引用。這樣的形式的程式碼在設計模式上講稱為合成設計模式
1.不要把程式只當程式
2.引用傳遞除了進行資料的分析之外,還需要掌握類與類的聯絡使用
3.程式碼鏈的使用必須熟練