首頁 > Java > java教程 > 主體

java中this引用及物件建構初始化的方法

WBOY
發布: 2023-05-14 18:40:06
轉載
1002 人瀏覽過

    1. this 引用

    1.1 為什麼要有this引用

    先來寫一個日期類的例子:

    public class classCode {
        public int year;
        public int month;
        public int day;
        public void setDay(int y, int m, int d){
            year = y;
            month = m;
            day = d;
        }
        public void printDate(){
            System.out.println(year + "-" + month + "-" + day);
        }
        public static void main(String[] args) {
            // 构造三个日期类型的对象 d1 d2 d3
            classCode Date1 = new classCode();
            classCode Date2 = new classCode();
            classCode Date3 = new classCode();
    
            // 对d1,d2,d3的日期设置
            Date1.setDay(2022, 8, 9);
            Date2.setDay(2023, 8, 9);
            Date3.setDay(2024, 8, 9);
    
            //打印日期的内容
            Date1.printDate();
            Date2.printDate();
            Date3.printDate();
        }
    }
    登入後複製

    java中this引用及物件建構初始化的方法

    以上程式碼定義了一個日期類,然後在main方法中建立了三個對象,並透過classCode類中的成員方法對物件進行設定和列印,程式碼整體邏輯非常簡單,沒有任何問題。

    有兩個要注意的地方:

    1.形參名不小心與成員變數名稱相同:

    public void setDay(int year, int month, int day){ 
        year = year;
        month = month;
        day = day; 
    }
    登入後複製

    那函數體中到底是誰給誰賦值?成員變數給成員變數?參數給參數?參數給成員變數?成員變數參數?

    2.三個物件都在呼叫setDate和printDate函數,但是這兩個函數中沒有任何關於物件的說明,setDate和printDate函數如何知道列印的是哪個物件的資料呢?

    java中this引用及物件建構初始化的方法

    可以看到如果形參名和成員變數名的話,賦值以後變數的值為0,表示並沒有賦值成功。

    那該怎麼做呢?往下面看。

    1.2 什麼是this引用

    this引用指向當前物件(成員方法執行時間呼叫該成員方法的物件),在成員方法中所有成員變數的操作,都是透過該引用去訪問只不過所有的操作對使用者是透明的,也就是使用者不需要來傳遞,編譯器自動完成。

    改進之後的程式碼:

    public void setDay(int year, int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;
    }
    登入後複製

    java中this引用及物件建構初始化的方法

    #可以看到新增 this 引用後,賦值成功。
    this 是預設新增的。即使是不加 this,也會有一個預設新增的 this。但不加的話,如果形參名和成員變數名相同就會帶來問題。

    在下面程式碼中,可以看到三個物件都在呼叫setDateprintDate 函數,而且也沒有說明,那該怎麼知道列印的是哪一個對象的資料?

    public static void main(String[] args) {
         // 构造三个日期类型的对象 Date1 Date2 Date3
         Date Date1 = new Date();
         Date Date2 = new Date();
         Date Date3 = new Date();
    
         // 对Date1,Date2,Date3的日期设置
         Date1.setDay(2022, 8, 9);
         Date2.setDay(2023, 8, 9);
         Date3.setDay(2024, 8, 9);
    
         //打印日期的内容
         Date1.printDate();
         Date2.printDate();
         Date3.printDate();
    }
    登入後複製

    可以透過下面兩點兩點來判斷列印哪個物件:

    • 前面的物件是哪個對象,列印哪個物件的數據

    • 隱藏的參數。

    public void setDay(Date this, int y, int m, int d){
        this.year = y;
        this.month = m;
        this.day = d;
    }
    public void printDate(Date this){
        System.out.println(this.year +"-"+ this.month +"-"+ this.day);
    }
    登入後複製

    this 的三種使用方式:

    • this.成員變數

    • this.存取成員方法

    • this();存取建構方法

    1.3 this引用的特性

    • this的類型:對應類別類型引用,即哪個物件呼叫就是哪個物件的引用類別。

    • this只能在"成員方法"中使用。

    • 在"成員方法"中,this只能引用當前對象,不能再引用其他對象。

    • this是「成員方法」第一個隱藏的參數,編譯器會自動傳遞,當成員方法執行時,編譯器會負責將呼叫成員方法。

    物件的參考傳遞給該成員方法,this負責來接收。

    就算成員變數名稱與形參名不相同也建議把 this 寫上,這相當於一種保護措施,而且也是一種好的程式設計規範。

    1.4 this引用練習題

    寫一個學術類,有姓名、年齡等屬性,然後透過一個方法來設定這些屬性的值,其次透過寫兩個方法,在一個方法當中使用this呼叫另一個方法。

    public class Student {
        public String name;
        public int age;
    
        public void setStudent(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void printStudent() {
            System.out.println(this.name + "->" + this.age);
        }
    
        public static void main(String[] args) {
            Student student = new Student();
            student.setStudent("zhangsan", 19);
            student.printStudent();
        }
    }
    登入後複製

    java中this引用及物件建構初始化的方法

    2. 物件的建構與初始化

    #2.1 如何初始化物件

    透過前面知識點的學習知道,在Java方法內部定義一個局部變數時,必須初始化,否則會編譯失敗。

    public static void main(String[] args) {
        int a;
        System.out.println(a);
    }// Error:(26, 28) java: 可能尚未初始化变量a.
    登入後複製

    如果是一個物件即使是沒賦值也不會報錯,因為這是一個引用變數。

     public static void main(String[] args) {
            // 构造一个日期类型的对象 
            Date date = new Date();
            date.setDay(2022, 8, 9);
            //打印日期的内容
            date.printDate();
        }//代码可以正常通过编译
    登入後複製

    透過上述範例發現兩個問題:

    • #每次物件建立好後都呼叫setDate方法設定具體日期,比較麻煩,那物件該如何初始化?

    • 局部變數必須要初始化才能使用,為什麼欄位宣告之後沒有給值依然可以使用?

    這就引入了建構方法。接著往下看。

    2.2 建構方法

    2.2.1 概念

    建構方法(也稱為建構器)是一個特殊的成員方法,名字必須與類別名稱相同,在創建物件時,由編譯器自動調用,並且在整個物件的生命週期內只調用一次。

    public class Student {
        public String name;
        public int age;
        public Student(){//这是一个构造方法
            System.out.println("不带参数的构造方法");
        }
        public Student(String name, int age) {//这是一个构造方法
            System.out.println("带参数的构造方法");
            this.name = name;
            this.age = age;
        }
        public void setStudent(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public void printStudent() {
            System.out.println(this.name + "->" + this.age);
        }
        public static void main(String[] args) {
            Student student = new Student();//这一行是构造方法的调用
        }
    }
    登入後複製

    java中this引用及物件建構初始化的方法

    Student student = new Student();
    new在实例化对象,而实例化对象一定会调用构造方法。

    注意:当我们没有提供构造方法时,编译器会自动提供一个不带参数的构造方法。

    2.2.2 特性
    • 名字必须与类名相同。

    • 没有返回值类型,设置为void也不行。

    • 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次。

    • 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法。

     public Student(){//不带参数的构造方法
            System.out.println("不带参数的构造方法");
        }
        public Student(String name, int age) {//带两个参数的构造方法
            System.out.println("带参数的构造方法");
            this.name = name;
            this.age = age;
    
        }
    登入後複製

    上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载。

    如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。

    public class Work {
        public int one = 1;
        public int three = 3;
        public int two = 2;
    
        public void printWork() {
            System.out.println(one + "-" + two + "-" + three);
        }
    
        public static void main(String[] args) {
            Work work = new Work();
            work.printWork();
        }
    }
    登入後複製

    java中this引用及物件建構初始化的方法

    上述Work类中,没有定义任何构造方法,编译器会默认生成一个不带参数的构造方法。

    那如何调用带参数的构造方法呢?

    public class Work {
        public int one = 1;
        public int three = 3;
        public int two = 2;
    
        public Work(int one, int two, int three) {
            System.out.println("带参数的构造方法");
            this.one = one;
            this.two = two;
            this.three = three;
        }
    
        public void printWork() {
            System.out.println(one + "-" + two + "-" + three);
        }
    
        public static void main(String[] args) {
            Work work = new Work(3, 6, 9);
            work.printWork();
        }
    }
    登入後複製

    java中this引用及物件建構初始化的方法

    注意:一旦用户定义,编译器则不再生成。

    构造方法中,可以通过this调用其他构造方法来简化代码。

     public Work() {
            this(10, 20, 30);//调用本类当中其他的构造方法
            System.out.println("不带参数的的构造方法");
        }
    
        public Work(int one, int two, int three) {
            System.out.println("带参数的构造方法");
            this.one = one;
            this.two = two;
            this.three = three;
        }
    登入後複製

    注意:

    • this调用必须在构造方法里面,

    • 要在在第一行,

    • 不能写成循环调用。

    绝大多数情况下使用public来修饰,特殊场景下会被private修饰(后序讲单例模式时会遇到)

    2.3 默认初始化

    为什么使用成员变量不需要初始化呢?

    java中this引用及物件建構初始化的方法

    在程序层面只是简单的一条语句,在JVM(以后讲)层面需要做好多事情,下面简单介绍下:

    • 检测对象对应的类是否加载了,如果没有加载则加载

    • 为对象分配内存空间

    • 处理并发安全问题

    比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突初始化所分配的空间
    即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值

    比如:

    java中this引用及物件建構初始化的方法

    设置对象头信息(关于对象内存模型后面会介绍)调用构造方法,给对象中各个成员赋值

    2.4 就地初始化

    定义成员变量的时候就已经赋值好了。

    public class HardWork {
        public int a = 10;//就地初始化
        public int b = 20;//就地初始化
        public String c = "zhangsan";//就地初始化
    
        public void setWork(int a,  int b, String c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    
        public void printWork() {
            System.out.println(a + "-" + b + "-" + c);
        }
        public static void main(String[] args) {
            HardWork work = new HardWork();
            work.printWork();
            System.out.println();
        }
    }
    登入後複製

    java中this引用及物件建構初始化的方法

    注意:代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中。

    以上是java中this引用及物件建構初始化的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    相關標籤:
    來源:yisu.com
    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
    熱門教學
    更多>
    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板