Java——引用傳遞實例分析(進階分析、對象比較、類與類的關聯實現)

目錄

1、引用傳遞進階分析

2、對象比較

3、引用傳遞實際應用

4、總結


 

1、引用傳遞進階分析

引用傳遞是Java的精髓所在,也是初學者比較難學的地方。下面通過三個程序進行分析。

【舉例】:第一個,較簡單

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Demo demo = new Demo(100);
        fun(demo);
        System.out.println(demo.getNum());//輸出30
    }

    private void fun(Demo temp) {
        temp.setNum(30);
    }

    class Demo{
        private int num =10;

        public Demo(int num){
            this.num = num;
        }

        public int getNum() {
            return num;
        }

        public void setNum(int num) {
            this.num = num;
        }
    }

【舉例】:第二個

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String str = "hello";
        fun(str);
        System.out.println(str);  //輸出hello
    }

    public static void fun(String temp) {
        temp = "world";
    }

以上輸出的是hello,注意字符串一旦聲明則不可改變,字符串內容的改變依靠的是引用的改變實現,觀察如下內存分析圖:

【舉例】:第三個

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Demo demo = new Demo("world");
        fun(demo);
        System.out.println(demo.getMsg());//輸出MLDN
    }

    public static void fun(Demo temp){
        temp.setMsg("MLDN");
    }

    class Demo{
        private String msg = "Hello";

        public Demo(String msg) {
            this.msg = msg;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

基於String是引用數據類型的認知,見如下內存分析圖:

引用傳遞一定要耐心使用內存分析,String這種類型 數據需要進行特殊處理。

2、對象比較

對象的比較就是判斷兩個對象是否相等,目前對象是否相等只能依靠地址是否相同來完成,但存在地址不同,內容相同的情況,好比String種的==與equals()。

要實現對象比較,首先必須進行對象種每一個屬性內容進行比較,若完全相同,則爲同一個對象,否則不同。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        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 = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }
    }

以上代碼雖然實現了功能,但是可以進一步優化,這種對象的比較操作應該是由自己完成,這時可以在Person類中增加compare方法。具體如下,注意要考慮null和自己與自己比較的場景。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Person perA = new Person("張三",20);
        Person perB = new Person("李四",20);
        if(perA.compare(perB)){
            System.out.println("是同一個人");
        }else {
            System.out.println("不是同一個人");
        }

    }

    class Person{
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }
        //接收要比較的對象,在本方法種有隱藏的對象this
        public boolean compare(Person person){
            if(person==null){ //避免null異常
                return false;
            }
            
            if(this == person){ //防止自己與自己比較
                return true;
            }
            if(this.name.equals(person.name) && this.age== person.age){
                return true;
            }
            return false;
        }
    }

對象比較一般是在分析層次上使用,而實際開發種,只有String應用的比較多。

3、引用傳遞實際應用

程序是生活的抽象,日常生活中的概念實際都可以用程序描述,eg:一個人有一輛車。

描述以上概念前,有這樣一個對比,若現在進行數據庫的設計,若描述以上操作形式,數據庫表該如何設計?需要兩個數據庫表;以上進行類的設計,實際也需要兩個類: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 getPersonInfo(){
            return "編號:"+this.pid+",姓名:"+this.name;
        }

        public Car getCar() {
            return car;
        }

        public void setCar(Car car) {
            this.car = car;
        }
    }

    class Car{
        private String cname;
        private Person person; //一車屬於一人

        public Car(String cname) {
            this.cname = cname;
        }

        public String getCarInfo(){
            return "汽車名稱:"+this.cname;
        }

        public Person getPerson() {
            return person;
        }

        public void setPerson(Person person) {
            this.person = person;
        }
    }

以上程序中使用了自定義的數據類型,Person和Car都是類。隨後進行測試:

  • (1)設置內容
  • (2)取出內容
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //(1)根據已有結構設置內容
        Person per = new Person(1,"張三");
        Car car = new Car("奔馳");
        per.setCar(car); //人有車了
        car.setPerson(per);//車屬於一個人了
        //(2)根據關係取出數據
        System.out.println(per.getPersonInfo());
        System.out.println(per.getCar().getCarInfo());//代碼鏈
        System.out.println(car.getPerson().getPersonInfo());//代碼鏈
    }

以上就是典型的一對一關係實現,可以進一步擴展下,比如每個人還有孩子,每個孩子還有車。這裏孩子也是人,具備跟人一樣的屬性信息,那麼可以在Person中設置孩子的屬性。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //(1)根據已有結構設置內容
        Person per = new Person(1,"張三");
        Person child = new Person(2,"張小三");
        Car car = new Car("奔馳");
        Car car1 = new Car("奧迪");
        per.setCar(car); //人有車了
        per.setChild(child); //人有一個孩子
        child.setCar(car1);//孩子有一個車
        car.setPerson(per);//車屬於一個人了
        //(2)根據關係取出數據
       //找到一個人的孩子信息
        System.out.println(per.getChild().getPersonInfo());
        //根據父親的車-父親的車-父親孩子-孩子的車信息
        System.out.println(per.car.getPerson().getChild().getCar().getCarInfo());
    }

    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 String getPersonInfo(){
            return "編號:"+this.pid+",姓名:"+this.name;
        }

        public Car getCar() {
            return car;
        }

        public void setCar(Car car) {
            this.car = car;
        }

        public Person getChild() {
            return child;
        }

        public void setChild(Person child) {
            this.child = child;
        }
    }

    class Car{
        private String cname;
        private Person person; //一車屬於一人

        public Car(String cname) {
            this.cname = cname;
        }

        public String getCarInfo(){
            return "汽車名稱:"+this.cname;
        }

        public Person getPerson() {
            return person;
        }

        public void setPerson(Person person) {
            this.person = person;
        }
    }

引用的關係,可以描述不同類之間的關聯。現實生活中這樣的設計實質上並不麻煩,理論上任何事物都可以進行抽象整合,比如一臺電腦:

class 內存{}
class 硬盤{}
class 顯卡{}
class CPU{}
class 鍵盤{}
class 鼠標{}
class 主板{
    private CPU  對象;
    private 內存 對象{};
    private 硬盤 對象{};
    private 顯卡 對象{};

}
class 電腦{
    private 主板 對象;
    private 鼠標 對象;
    private 鍵盤 對象
}

以上同樣屬於引用,這樣的方式在設計模式中屬於合成設計模型。

4、總結

  • 不要把程序當成純粹的程序;
  • 引用傳遞除了進行數據分析外,還要掌握類與類的聯繫使用;
  • 代碼鏈的使用必須掌握

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章