java中的this引用及對象構(gòu)造初始化
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) { // 構(gòu)造三個日期類型的對象 d1 d2 d3 classCode Date1 = new classCode(); classCode Date2 = new classCode(); classCode Date3 = new classCode(); // 對d1,d2,d3的日期設(shè)置 Date1.setDay(2022, 8, 9); Date2.setDay(2023, 8, 9); Date3.setDay(2024, 8, 9); //打印日期的內(nèi)容 Date1.printDate(); Date2.printDate(); Date3.printDate(); } }
以上代碼定義了一個日期類,然后main方法中創(chuàng)建了三個對象,并通過classCode類中的成員方法對對象進行設(shè)置和打印,代碼整體邏輯非常簡單,沒有任何問題。
有兩個需要注意的地方:
1.形參名不小心與成員變量名相同:
public void setDay(int year, int month, int day){ year = year; month = month; day = day; }
那函數(shù)體中到底是誰給誰賦值?成員變量給成員變量?參數(shù)給參數(shù)?參數(shù)給成員變量?成員變量參數(shù)?
2.三個對象都在調(diào)用setDate和printDate函數(shù),但是這兩個函數(shù)中沒有任何有關(guān)對象的說明,setDate和printDate函數(shù)如何知道打印的是哪個對象的數(shù)據(jù)呢?
可以看到如果形參名和成員變量名的話,賦值以后變量的值為0,說明并沒有賦值成功。
那應(yīng)該怎么做呢?往下面看。
1.2 什么是this引用
this引用指向當前對象(成員方法運行時調(diào)用該成員方法的對象),在成員方法中所有成員變量的操作,都是通過該引用去訪問。只不過所有的操作對用戶是透明的,即用戶不需要來傳遞,編譯器自動完成。
改進之后的代碼:
public void setDay(int year, int month, int day){ this.year = year; this.month = month; this.day = day; }
可以看到添加 this 引用后,賦值成功。
this 是默認添加的。即使是不加 this,也會有一個默認添加的 this。但是不添加的話,如果形參名和成員變量名相同就會帶來問題。
在下面代碼中,可以看到三個對象都在調(diào)用 setDate 和 printDate 函數(shù),而且也沒有說明,那該怎么知道打印的是哪個對象的數(shù)據(jù)?
public static void main(String[] args) { // 構(gòu)造三個日期類型的對象 Date1 Date2 Date3 Date Date1 = new Date(); Date Date2 = new Date(); Date Date3 = new Date(); // 對Date1,Date2,Date3的日期設(shè)置 Date1.setDay(2022, 8, 9); Date2.setDay(2023, 8, 9); Date3.setDay(2024, 8, 9); //打印日期的內(nèi)容 Date1.printDate(); Date2.printDate(); Date3.printDate(); }
可以通過下面兩點兩點來判斷打印哪個對象:
- 前面的對象是哪個對象,打印哪個對象的數(shù)據(jù)
- 隱藏的參數(shù)。
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();訪問構(gòu)造方法
1.3 this引用的特性
- this的類型:對應(yīng)類類型引用,即哪個對象調(diào)用就是哪個對象的引用類。
- this只能在"成員方法"中使用。
- 在"成員方法"中,this只能引用當前對象,不能再引用其他對象。
- this是“成員方法”第一個隱藏的參數(shù),編譯器會自動傳遞,在成員方法執(zhí)行時,編譯器會負責(zé)將調(diào)用成員方法。
對象的引用傳遞給該成員方法,this負責(zé)來接收。
就算成員變量名與形參名不相同也建議把 this 寫上,這相當于一種保護措施,而且也是一種好的編程規(guī)范。
1.4 this引用練習(xí)題
寫一個學(xué)術(shù)類,有姓名、年齡等屬性,然后通過一個方法來設(shè)置這些屬性的值,其次通過寫兩個方法,在一個方法當中使用this調(diào)用另一個方法。
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(); } }
2. 對象的構(gòu)造及初始化
2.1 如何初始化對象
通過前面知識點的學(xué)習(xí)知道,在Java方法內(nèi)部定義一個局部變量時,必須要初始化,否則會編譯失敗。
public static void main(String[] args) { int a; System.out.println(a); }// Error:(26, 28) java: 可能尚未初始化變量a.
如果是一個對象即使是沒賦值也不會報錯,因為這是一個引用變量。
public static void main(String[] args) { // 構(gòu)造一個日期類型的對象 Date date = new Date(); date.setDay(2022, 8, 9); //打印日期的內(nèi)容 date.printDate(); }//代碼可以正常通過編譯
通過上述例子發(fā)現(xiàn)兩個問題:
- 每次對象創(chuàng)建好后調(diào)用setDate方法設(shè)置具體日期,比較麻煩,那對象該如何初始化?
- 局部變量必須要初始化才能使用,為什么字段聲明之后沒有給值依然可以使用?
這就引入了構(gòu)造方法。接著往下看。
2.2 構(gòu)造方法
2.2.1 概念
構(gòu)造方法(也稱為構(gòu)造器)是一個特殊的成員方法,名字必須與類名相同,在創(chuàng)建對象時,由編譯器自動調(diào)用,并且在整個對象的生命周期內(nèi)只調(diào)用一次。
public class Student { public String name; public int age; public Student(){//這是一個構(gòu)造方法 System.out.println("不帶參數(shù)的構(gòu)造方法"); } public Student(String name, int age) {//這是一個構(gòu)造方法 System.out.println("帶參數(shù)的構(gòu)造方法"); 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();//這一行是構(gòu)造方法的調(diào)用 } }
Student student = new Student();
new在實例化對象,而實例化對象一定會調(diào)用構(gòu)造方法。
注意:當我們沒有提供構(gòu)造方法時,編譯器會自動提供一個不帶參數(shù)的構(gòu)造方法。
2.2.2 特性
- 名字必須與類名相同。
- 沒有返回值類型,設(shè)置為void也不行。
- 創(chuàng)建對象時由編譯器自動調(diào)用,并且在對象的生命周期內(nèi)只調(diào)用一次。
- 構(gòu)造方法可以重載(用戶根據(jù)自己的需求提供不同參數(shù)的構(gòu)造方法。
public Student(){//不帶參數(shù)的構(gòu)造方法 System.out.println("不帶參數(shù)的構(gòu)造方法"); } public Student(String name, int age) {//帶兩個參數(shù)的構(gòu)造方法 System.out.println("帶參數(shù)的構(gòu)造方法"); this.name = name; this.age = age; }
上述兩個構(gòu)造方法:名字相同,參數(shù)列表不同,因此構(gòu)成了方法重載。
如果用戶沒有顯式定義,編譯器會生成一份默認的構(gòu)造方法,生成的默認構(gòu)造方法一定是無參的。
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(); } }
上述Work類中,沒有定義任何構(gòu)造方法,編譯器會默認生成一個不帶參數(shù)的構(gòu)造方法。
那如何調(diào)用帶參數(shù)的構(gòu)造方法呢?
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("帶參數(shù)的構(gòu)造方法"); 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(); } }
注意:一旦用戶定義,編譯器則不再生成。
構(gòu)造方法中,可以通過this調(diào)用其他構(gòu)造方法來簡化代碼。
public Work() { this(10, 20, 30);//調(diào)用本類當中其他的構(gòu)造方法 System.out.println("不帶參數(shù)的的構(gòu)造方法"); } public Work(int one, int two, int three) { System.out.println("帶參數(shù)的構(gòu)造方法"); this.one = one; this.two = two; this.three = three; }
注意:
- this調(diào)用必須在構(gòu)造方法里面,
- 要在在第一行,
- 不能寫成循環(huán)調(diào)用。
絕大多數(shù)情況下使用public來修飾,特殊場景下會被private修飾(后序講單例模式時會遇到)
2.3 默認初始化
為什么使用成員變量不需要初始化呢?
在程序?qū)用嬷皇呛唵蔚囊粭l語句,在JVM(以后講)層面需要做好多事情,下面簡單介紹下:
- 檢測對象對應(yīng)的類是否加載了,如果沒有加載則加載
- 為對象分配內(nèi)存空間
- 處理并發(fā)安全問題
比如:多個線程同時申請對象,JVM要保證給對象分配的空間不沖突初始化所分配的空間
即:對象空間被申請好之后,對象中包含的成員已經(jīng)設(shè)置好了初始值
比如:
設(shè)置對象頭信息(關(guān)于對象內(nèi)存模型后面會介紹)調(diào)用構(gòu)造方法,給對象中各個成員賦值
2.4 就地初始化
定義成員變量的時候就已經(jīng)賦值好了。
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(); } }
注意:代碼編譯完成后,編譯器會將所有給成員初始化的這些語句添加到各個構(gòu)造函數(shù)中。
到此這篇關(guān)于java中的this引用及對象構(gòu)造初始化的文章就介紹到這了,更多相關(guān)java this引用 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java網(wǎng)絡(luò)編程UDP協(xié)議發(fā)送接收數(shù)據(jù)
這篇文章主要為大家詳細介紹了Java網(wǎng)絡(luò)編程UDP協(xié)議發(fā)送接收數(shù)據(jù),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08SpringBoot2整合Drools規(guī)則引擎及案例詳解
這篇文章主要介紹了SpringBoot2整合Drools規(guī)則引擎及案例詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-10-10Java并發(fā)編程之詳解ConcurrentHashMap類
在之前的文章中已經(jīng)為大家介紹了java并發(fā)編程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口,本文為系列文章第八篇.需要的朋友可以參考下2021-06-06idea中使用Inputstream流導(dǎo)致中文亂碼解決方法
很多朋友遇到一個措手不及的問題當idea中使用Inputstream流導(dǎo)致中文亂碼及Java FileInputStream讀中文亂碼問題,針對這兩個問題很多朋友不知道該如何解決,下面小編把解決方案分享給大家供大家參考2021-05-05java使用Socket實現(xiàn)SMTP協(xié)議發(fā)送郵件
這篇文章主要為大家詳細介紹了java使用Socket實現(xiàn)SMTP協(xié)議發(fā)送郵件的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-05-05java.lang.IllegalStateException異常解決
異常是程序在執(zhí)行過程中遇到的錯誤或異常情況,本文就來介紹一下java.lang.IllegalStateException異常解決,感興趣的可以了解一下2023-11-11