java中的this引用及對(duì)象構(gòu)造初始化
1. this 引用
1.1 為什么要有this引用
先來寫一個(gè)日期類的例子:
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)造三個(gè)日期類型的對(duì)象 d1 d2 d3
classCode Date1 = new classCode();
classCode Date2 = new classCode();
classCode Date3 = new classCode();
// 對(duì)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();
}
}
以上代碼定義了一個(gè)日期類,然后main方法中創(chuàng)建了三個(gè)對(duì)象,并通過classCode類中的成員方法對(duì)對(duì)象進(jìn)行設(shè)置和打印,代碼整體邏輯非常簡(jiǎn)單,沒有任何問題。
有兩個(gè)需要注意的地方:
1.形參名不小心與成員變量名相同:
public void setDay(int year, int month, int day){
year = year;
month = month;
day = day;
}那函數(shù)體中到底是誰給誰賦值?成員變量給成員變量?參數(shù)給參數(shù)?參數(shù)給成員變量?成員變量參數(shù)?
2.三個(gè)對(duì)象都在調(diào)用setDate和printDate函數(shù),但是這兩個(gè)函數(shù)中沒有任何有關(guān)對(duì)象的說明,setDate和printDate函數(shù)如何知道打印的是哪個(gè)對(duì)象的數(shù)據(jù)呢?

可以看到如果形參名和成員變量名的話,賦值以后變量的值為0,說明并沒有賦值成功。
那應(yīng)該怎么做呢?往下面看。
1.2 什么是this引用
this引用指向當(dāng)前對(duì)象(成員方法運(yùn)行時(shí)調(diào)用該成員方法的對(duì)象),在成員方法中所有成員變量的操作,都是通過該引用去訪問。只不過所有的操作對(duì)用戶是透明的,即用戶不需要來傳遞,編譯器自動(dòng)完成。
改進(jìn)之后的代碼:
public void setDay(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
可以看到添加 this 引用后,賦值成功。
this 是默認(rèn)添加的。即使是不加 this,也會(huì)有一個(gè)默認(rèn)添加的 this。但是不添加的話,如果形參名和成員變量名相同就會(huì)帶來問題。
在下面代碼中,可以看到三個(gè)對(duì)象都在調(diào)用 setDate 和 printDate 函數(shù),而且也沒有說明,那該怎么知道打印的是哪個(gè)對(duì)象的數(shù)據(jù)?
public static void main(String[] args) {
// 構(gòu)造三個(gè)日期類型的對(duì)象 Date1 Date2 Date3
Date Date1 = new Date();
Date Date2 = new Date();
Date Date3 = new Date();
// 對(duì)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();
}可以通過下面兩點(diǎn)兩點(diǎn)來判斷打印哪個(gè)對(duì)象:
- 前面的對(duì)象是哪個(gè)對(duì)象,打印哪個(gè)對(duì)象的數(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的類型:對(duì)應(yīng)類類型引用,即哪個(gè)對(duì)象調(diào)用就是哪個(gè)對(duì)象的引用類。
- this只能在"成員方法"中使用。
- 在"成員方法"中,this只能引用當(dāng)前對(duì)象,不能再引用其他對(duì)象。
- this是“成員方法”第一個(gè)隱藏的參數(shù),編譯器會(huì)自動(dòng)傳遞,在成員方法執(zhí)行時(shí),編譯器會(huì)負(fù)責(zé)將調(diào)用成員方法。
對(duì)象的引用傳遞給該成員方法,this負(fù)責(zé)來接收。
就算成員變量名與形參名不相同也建議把 this 寫上,這相當(dāng)于一種保護(hù)措施,而且也是一種好的編程規(guī)范。
1.4 this引用練習(xí)題
寫一個(gè)學(xué)術(shù)類,有姓名、年齡等屬性,然后通過一個(gè)方法來設(shè)置這些屬性的值,其次通過寫兩個(gè)方法,在一個(gè)方法當(dāng)中使用this調(diào)用另一個(gè)方法。
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. 對(duì)象的構(gòu)造及初始化
2.1 如何初始化對(duì)象
通過前面知識(shí)點(diǎn)的學(xué)習(xí)知道,在Java方法內(nèi)部定義一個(gè)局部變量時(shí),必須要初始化,否則會(huì)編譯失敗。
public static void main(String[] args) {
int a;
System.out.println(a);
}// Error:(26, 28) java: 可能尚未初始化變量a.如果是一個(gè)對(duì)象即使是沒賦值也不會(huì)報(bào)錯(cuò),因?yàn)檫@是一個(gè)引用變量。
public static void main(String[] args) {
// 構(gòu)造一個(gè)日期類型的對(duì)象
Date date = new Date();
date.setDay(2022, 8, 9);
//打印日期的內(nèi)容
date.printDate();
}//代碼可以正常通過編譯通過上述例子發(fā)現(xiàn)兩個(gè)問題:
- 每次對(duì)象創(chuàng)建好后調(diào)用setDate方法設(shè)置具體日期,比較麻煩,那對(duì)象該如何初始化?
- 局部變量必須要初始化才能使用,為什么字段聲明之后沒有給值依然可以使用?
這就引入了構(gòu)造方法。接著往下看。
2.2 構(gòu)造方法
2.2.1 概念
構(gòu)造方法(也稱為構(gòu)造器)是一個(gè)特殊的成員方法,名字必須與類名相同,在創(chuàng)建對(duì)象時(shí),由編譯器自動(dòng)調(diào)用,并且在整個(gè)對(duì)象的生命周期內(nèi)只調(diào)用一次。
public class Student {
public String name;
public int age;
public Student(){//這是一個(gè)構(gòu)造方法
System.out.println("不帶參數(shù)的構(gòu)造方法");
}
public Student(String name, int age) {//這是一個(gè)構(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在實(shí)例化對(duì)象,而實(shí)例化對(duì)象一定會(huì)調(diào)用構(gòu)造方法。
注意:當(dāng)我們沒有提供構(gòu)造方法時(shí),編譯器會(huì)自動(dòng)提供一個(gè)不帶參數(shù)的構(gòu)造方法。
2.2.2 特性
- 名字必須與類名相同。
- 沒有返回值類型,設(shè)置為void也不行。
- 創(chuàng)建對(duì)象時(shí)由編譯器自動(dòng)調(diào)用,并且在對(duì)象的生命周期內(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) {//帶兩個(gè)參數(shù)的構(gòu)造方法
System.out.println("帶參數(shù)的構(gòu)造方法");
this.name = name;
this.age = age;
}上述兩個(gè)構(gòu)造方法:名字相同,參數(shù)列表不同,因此構(gòu)成了方法重載。
如果用戶沒有顯式定義,編譯器會(huì)生成一份默認(rèn)的構(gòu)造方法,生成的默認(rèn)構(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)造方法,編譯器會(huì)默認(rèn)生成一個(gè)不帶參數(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)造方法來簡(jiǎn)化代碼。
public Work() {
this(10, 20, 30);//調(diào)用本類當(dāng)中其他的構(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來修飾,特殊場(chǎng)景下會(huì)被private修飾(后序講單例模式時(shí)會(huì)遇到)
2.3 默認(rèn)初始化
為什么使用成員變量不需要初始化呢?

在程序?qū)用嬷皇呛?jiǎn)單的一條語句,在JVM(以后講)層面需要做好多事情,下面簡(jiǎn)單介紹下:
- 檢測(cè)對(duì)象對(duì)應(yīng)的類是否加載了,如果沒有加載則加載
- 為對(duì)象分配內(nèi)存空間
- 處理并發(fā)安全問題
比如:多個(gè)線程同時(shí)申請(qǐng)對(duì)象,JVM要保證給對(duì)象分配的空間不沖突初始化所分配的空間
即:對(duì)象空間被申請(qǐng)好之后,對(duì)象中包含的成員已經(jīng)設(shè)置好了初始值
比如:

設(shè)置對(duì)象頭信息(關(guān)于對(duì)象內(nèi)存模型后面會(huì)介紹)調(diào)用構(gòu)造方法,給對(duì)象中各個(gè)成員賦值
2.4 就地初始化
定義成員變量的時(shí)候就已經(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();
}
}
注意:代碼編譯完成后,編譯器會(huì)將所有給成員初始化的這些語句添加到各個(gè)構(gòu)造函數(shù)中。
到此這篇關(guān)于java中的this引用及對(duì)象構(gòu)造初始化的文章就介紹到這了,更多相關(guān)java this引用 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot結(jié)果封裝和異常攔截的實(shí)現(xiàn)示例
SpringBoot 項(xiàng)目中,我們通常需要將結(jié)果數(shù)據(jù)封裝成特定的格式,以方便客戶端進(jìn)行處理,本文主要介紹了SpringBoot?優(yōu)雅的結(jié)果封裝和異常攔截,感興趣的可以了解一下2023-08-08
Java中jdk1.8和jdk17相互切換實(shí)戰(zhàn)步驟
之前做Java項(xiàng)目時(shí)一直用的是jdk1.8,現(xiàn)在想下載另一個(gè)jdk版本17,并且在之后的使用中可以進(jìn)行相互切換,下面這篇文章主要給大家介紹了關(guān)于Java中jdk1.8和jdk17相互切換的相關(guān)資料,需要的朋友可以參考下2023-05-05
Java設(shè)計(jì)模式之裝飾者模式詳解和代碼實(shí)例
這篇文章主要介紹了Java設(shè)計(jì)模式之裝飾者模式詳解和代碼實(shí)例,Decorator模式(別名Wrapper):動(dòng)態(tài)將職責(zé)附加到對(duì)象上,若要擴(kuò)展功能,裝飾者提供了比繼承更具彈性的代替方案,需要的朋友可以參考下2014-09-09
Postman實(shí)現(xiàn)傳List<String>集合
這篇文章主要介紹了Postman實(shí)現(xiàn)傳List<String>集合方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
配置idea將Java與數(shù)據(jù)庫連接起來實(shí)現(xiàn)一個(gè)簡(jiǎn)單的圖書管理系統(tǒng)
這篇文章主要給大家介紹了關(guān)于配置idea將Java與數(shù)據(jù)庫連接起來實(shí)現(xiàn)一個(gè)簡(jiǎn)單的圖書管理系統(tǒng)的相關(guān)資料,本文從基于Java的圖書管理系統(tǒng)的背景、系統(tǒng)設(shè)計(jì)、數(shù)據(jù)庫設(shè)計(jì)和系統(tǒng)實(shí)現(xiàn)等方面進(jìn)行了詳細(xì)的研究,需要的朋友可以參考下2023-12-12
Java設(shè)計(jì)模式以虹貓藍(lán)兔的故事講解橋接模式
橋接是用于把抽象化與實(shí)現(xiàn)化解耦,使二者可以獨(dú)立變化。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它通過提供抽象化和實(shí)現(xiàn)化之間的橋接結(jié)構(gòu),來實(shí)現(xiàn)二者的解耦。這種模式涉及到一個(gè)作為橋接的接口,使得實(shí)體類的功能獨(dú)立于接口實(shí)現(xiàn)類。這兩種類型的類可被結(jié)構(gòu)化改變而互不影響2022-04-04
springboot多數(shù)據(jù)源使用@Qualifier自動(dòng)注入無效的解決
這篇文章主要介紹了springboot多數(shù)據(jù)源使用@Qualifier自動(dòng)注入無效的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。也希望大家多多支持腳本之家2021-11-11

