Java?超詳細(xì)講解對(duì)象的構(gòu)造及初始化
如何初始化對(duì)象
我們知道再Java方法內(nèi)部定義一個(gè)局部變量的時(shí)候,必須要初始化,否則就會(huì)編譯失敗

要讓這串代碼通過(guò)編譯,很簡(jiǎn)單,只需要在正式使用a之前,給a設(shè)置一個(gè)初始值就好
那么對(duì)于創(chuàng)造好的對(duì)象來(lái)說(shuō),我們也要進(jìn)行相對(duì)應(yīng)的初始化
我們先寫一個(gè)Mydate的類
public class MyDate {
public int year;
public int month;
public int day;
/**
* 設(shè)置日期:
*/
public void setDate(int year,int month,int day) {
this.year = year;
this.month = month ;
this.day = day;
}
public void printDate() {
System.out.println("年:"+this.year+"月:"+this.month+"日:"+this.day);
}
public static void main(String[] args) {
// this.printDate();
MyDate myDate = new MyDate();
myDate.setDate(2022,3,25);
myDate.printDate();
MyDate myDate2 = new MyDate();
myDate2.setDate(2022,3,28);
myDate2.printDate();
}
}
我們可以看到,在Mydate類中,要在調(diào)用之前實(shí)現(xiàn)寫好setDate才能將具體的日期設(shè)置到對(duì)象當(dāng)中

我們通過(guò)這個(gè)例子就可以發(fā)現(xiàn)兩個(gè)問(wèn)題:
- 每次對(duì)象創(chuàng)建好之后調(diào)用setDate方法設(shè)置具體時(shí)期,比較麻煩,那么對(duì)象該如何初始化呢?
- 局部變量必須要初始化之后才能使用,那么為什么字段聲明之后沒(méi)有給初值,它依舊可以使用呢?
答案:
- 我們可以運(yùn)用構(gòu)造函數(shù)來(lái)進(jìn)行初始化
- 因?yàn)檫@里和main函數(shù)中定義的局部變量不同,編譯器會(huì)自動(dòng)為你的字段聲明的局部變量賦初始零值。
構(gòu)造方法
當(dāng)我們實(shí)例化一個(gè)對(duì)象的時(shí)候:必須會(huì)有這兩步,但并不是一定只有這兩步
- 為對(duì)象分配內(nèi)存
- 調(diào)用合適的構(gòu)造方法
構(gòu)造方法(也稱為構(gòu)造器)是一個(gè)特殊的成員方法,名字必須與類名相同,在創(chuàng)建對(duì)象的時(shí)候,由編譯器自動(dòng)調(diào)用,并且在整個(gè)對(duì)象的生命周期內(nèi)只調(diào)用一次
class Person {
public String name;
public int age;
//構(gòu)造方法:
//名字與類名相同,且沒(méi)有返回值類型,void也不行
//一般情況下使用public修飾
//在創(chuàng)建對(duì)象的時(shí)候由編譯器自動(dòng)調(diào)用,并且在對(duì)象的聲明周期內(nèi)只調(diào)用一次
public Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("構(gòu)造方法被調(diào)用了")
}
public void eat() {
System.out.println("吃飯!");
}
public void sleep() {
System.out.println("睡覺(jué)!");
}
public static void main(String[] args){
//在此處創(chuàng)建了一個(gè)Date類型的對(duì)象,并沒(méi)有顯式調(diào)用構(gòu)造函數(shù)
Person p = new Person("xiaohong",18);
p.eat();
}
}
??:構(gòu)造方法的作用就是對(duì)對(duì)象中的成員進(jìn)行初始化,并不負(fù)責(zé)給對(duì)象開辟空間

特性
- 名字必須和類名相同
- 沒(méi)有返回值類型,void也不行
- 創(chuàng)建對(duì)象時(shí)由編譯器自動(dòng)調(diào)用,并且在對(duì)象的生命周期內(nèi)只調(diào)用一次(相當(dāng)于人的出生)
- 構(gòu)造方法可以重載(用戶根據(jù)自己的需求提供不同參數(shù)的構(gòu)造方法)
class Student {
//屬性:成員變量-》類的內(nèi)部 方法的外部的
public String name;
public int age;
public double score ;
public String sex;
public Student() {
//調(diào)用本類中 帶有2個(gè)參數(shù)的構(gòu)造方法,第一個(gè)參數(shù)的類型是String,第2個(gè)參數(shù)的類型是int
this.age = 18;
System.out.println("這個(gè)是不帶參數(shù)的構(gòu)造方法!");
}
public Student(String name,int age) {
//this();
this.age = age;
this.name = name;
System.out.println("這個(gè)是帶2個(gè)參數(shù)的構(gòu)造方法!");
}
public Student(String name, int age, double score, String sex) {
this.name = name;
this.age = age;
this.score = score;
this.sex = sex;
System.out.println("帶4個(gè)參數(shù)的構(gòu)造方法!");
}
public void doClass() {
System.out.println(name+"正在上課!");
//this.doHomeWork();
}
public void doHomeWork(){
System.out.println(name+"正在寫作業(yè)");
}
public void show() {
System.out.println("姓名:"+name+" 年齡:"+age+" 學(xué)分:"+score+" 性別:"+sex);
}
}
//重載的時(shí)候
上述方法中:名字相同,參數(shù)列表不同,因此構(gòu)成了方法重載
如果用戶沒(méi)有顯式定義,編譯器會(huì)生成一份默認(rèn)的構(gòu)造方法,生成的默認(rèn)構(gòu)造方法一定是無(wú)參的。
class MyGirlFired {
public String name;
public int age;
public String eyes;
public void eat() {
System.out.println("吃火鍋!");
}
}
在上面的代碼中,沒(méi)有定義任何構(gòu)造方法,編譯器就會(huì)默認(rèn)為我們生成一個(gè)不帶參數(shù)的構(gòu)造方法
??:一旦用戶定義了,編譯器則不再生成任何構(gòu)造函數(shù)

class MyGirlFired {
public String name;
public int age;
public String eyes;
public MyGirlFired(String name,int age){
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("吃火鍋!");
}
public static void main(String[] args) {
//如果編譯器會(huì)生成,則生成的構(gòu)造方法一定是無(wú)參數(shù)的
//則此處創(chuàng)建對(duì)象是可以通過(guò)編譯的
//但實(shí)際上會(huì)報(bào)錯(cuò)
MyGirlFired xHong = new MyGirlFired();
}
}

在構(gòu)造方法中,可以通過(guò)this調(diào)用其他構(gòu)造方法來(lái)簡(jiǎn)化代碼
class Student {
//屬性:成員變量-》類的內(nèi)部 方法的外部的
public String name;
public int age;
public double score ;
public String sex;
public Student() {
//調(diào)用本類中 帶有2個(gè)參數(shù)的構(gòu)造方法,第一個(gè)參數(shù)的類型是String,第2個(gè)參數(shù)的類型是int
this("yumi",18);
//this("bit3",99,98.9,"女");
System.out.println("這個(gè)是不帶參數(shù)的構(gòu)造方法!");
}
public Student(String name,int age) {
//this();
this.age = age;
this.name = name;
System.out.println("這個(gè)是帶2個(gè)參數(shù)的構(gòu)造方法!");
}
public Student(String name, int age, double score, String sex) {
this.name = name;
this.age = age;
this.score = score;
this.sex = sex;
System.out.println("帶4個(gè)參數(shù)的構(gòu)造方法!");
}
public void doClass() {
System.out.println(name+"正在上課!");
//this.doHomeWork();
}
public void doHomeWork(){
System.out.println(name+"正在寫作業(yè)");
}
public void show() {
System.out.println("姓名:"+name+" 年齡:"+age+" 學(xué)分:"+score+" 性別:"+sex);
}
}
??注意:
- this()必須是構(gòu)造方法中的第一條語(yǔ)句,且只能放在構(gòu)造函數(shù)中
- 不能形成“環(huán)”
例如

絕大多數(shù)情況我們都用public來(lái)修飾,特殊場(chǎng)景下會(huì)被private修飾
默認(rèn)初始化
上面我們提到了一個(gè)問(wèn)題:為什么局部變量在使用時(shí)必須要用初始化,而成員變量可以不用呢?
public class Date {
public int year;
public int month;
public int day;
public Date(int year,int month,int day){
//成員變量在定義之前,并沒(méi)有給出初始值,那為什么就可以使用呢?
System.out.println(this.year);
System.out.println(this.month);
System.out.println(this.day);
}
public static void main(String[] args) {
//此處a并沒(méi)有初始化,編譯器報(bào)錯(cuò);
//Error:(24,28)Java:可能尚未初始化變量a
//int a;
//System.out.println(a);
Date d = new Date(2022,3,29);
}
}

要搞清楚這個(gè)過(guò)程,我們需要知道new關(guān)鍵字背后所發(fā)生的一些事情
Date d = new Date(2021,6,9);
在程序?qū)用嬷皇呛?jiǎn)單的一條語(yǔ)句,而在JVM層面則需要做好多事情
- 檢測(cè)對(duì)象對(duì)應(yīng)的類是否加載了,如果沒(méi)有加載則加載
- 為對(duì)象分配內(nèi)存空間
- 處理并發(fā)安全問(wèn)題
??比如:多個(gè)線程同時(shí)申請(qǐng)對(duì)象,JVM要保證給對(duì)象分配的空間不沖突
- 初始化所分配的空間
即:對(duì)象空間被申請(qǐng)好了之后,對(duì)象中包含的成員已經(jīng)設(shè)置好了初始值

| 數(shù)據(jù)類型 | 默認(rèn)值 |
|---|---|
| byte | 0 |
| char | ‘\u0000’ |
| short | 0 |
| int | 0 |
| long | 0L |
| boolean | false |
| float | 0.0f |
| double | 0.0 |
| reference | null |
- 設(shè)置對(duì)象頭信息(關(guān)于對(duì)象內(nèi)存模型后面再說(shuō))
- 調(diào)用構(gòu)造方法,是給對(duì)象中的各個(gè)成員賦值
就地初始化
在聲明成員變量時(shí),就直接給出了初始值
public class Date {
public int year;
public int month;
public int day;
public Date(){
System.out.println(this.year);
System.out.println(this.month);
System.out.println(this.day);
}
public Date(int year,int month,int day){
//成員變量在定義之前,并沒(méi)有給出初始值,那為什么就可以使用呢?
System.out.println(this.year);
System.out.println(this.month);
System.out.println(this.day);
}
public static void main(String[] args) {
//此處a并沒(méi)有初始化,編譯器報(bào)錯(cuò);
//Error:(24,28)Java:可能尚未初始化變量a
//int a;
//System.out.println(a);
Date d1 = new Date(2022,3,29);
Date d2 = new Date();
}
}
//運(yùn)行結(jié)果:
//0
//0
//0
//0
//0
//0
??注意:代碼編譯完成之后,編譯器會(huì)將所有成員初始化的這些語(yǔ)句添加到各個(gè)構(gòu)造函數(shù)中


5.一個(gè)類至少會(huì)有1個(gè)構(gòu)造函數(shù),就算你沒(méi)有寫!
6.構(gòu)造方法 本質(zhì) 就是來(lái)實(shí)例化對(duì)象的時(shí)候調(diào)用
(1)分配內(nèi)存
(2)調(diào)用合適的構(gòu)造方法
7.this可以用來(lái)調(diào)用本類中的其他構(gòu)造方法【構(gòu)造方法當(dāng)中使用】
且必須放在第一行!所以,只能在當(dāng)前構(gòu)造方法當(dāng)中,調(diào)用一次
8.this的用法:
- this.data 訪問(wèn)屬性
- this.func(); 訪問(wèn)方法
- this(); //用來(lái)調(diào)用本類中的其他構(gòu)造方法
9.this不能形成環(huán)。
有錯(cuò)誤請(qǐng)大家批評(píng)指正
感謝閱讀
到此這篇關(guān)于Java 超詳細(xì)講解對(duì)象的構(gòu)造及初始化的文章就介紹到這了,更多相關(guān)Java 對(duì)象的構(gòu)造內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Cloud與分布式系統(tǒng)簡(jiǎn)析
這篇文章主要介紹了Spring Cloud與分布式系統(tǒng)的相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-09-09
Java數(shù)據(jù)結(jié)構(gòu)之快速冪的實(shí)現(xiàn)
快速冪是用來(lái)解決求冪運(yùn)算的高效方式。本文將詳細(xì)為大家介紹如何利用Java實(shí)現(xiàn)快速冪,以及利用快速冪求解冪運(yùn)算問(wèn)題,需要的可以參考一下2022-03-03
SpringBoot靜態(tài)資源的訪問(wèn)方法詳細(xì)介紹
最近在做SpringBoot項(xiàng)目的時(shí)候遇到了“白頁(yè)”問(wèn)題,通過(guò)查資料對(duì)SpringBoot訪問(wèn)靜態(tài)資源做了總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-09-09
如何使用spring-ws發(fā)布webservice服務(wù)
文章介紹了如何使用Spring-WS發(fā)布Web服務(wù),包括添加依賴、創(chuàng)建XSD文件、生成JAXB實(shí)體、配置Endpoint、啟動(dòng)服務(wù)等步驟,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-11-11
JAVA初級(jí)項(xiàng)目——實(shí)現(xiàn)圖書管理系統(tǒng)
這篇文章主要介紹了JAVA如何實(shí)現(xiàn)圖書管理系統(tǒng),文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下2020-06-06
java數(shù)據(jù)結(jié)構(gòu)與算法之插入算法實(shí)現(xiàn)數(shù)值排序示例
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之插入算法實(shí)現(xiàn)數(shù)值排序的方法,結(jié)合簡(jiǎn)單實(shí)例形式分析了插入算法的節(jié)點(diǎn)操作與排序相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-08-08
淺談Java循環(huán)中的For和For-each哪個(gè)更快
本文主要介紹了淺談Java循環(huán)中的For和For-each哪個(gè)更快,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
SpringTask-Timer實(shí)現(xiàn)定時(shí)任務(wù)的詳細(xì)代碼
在項(xiàng)目中開發(fā)定時(shí)任務(wù)應(yīng)該一種比較常見的需求,今天通過(guò)示例代碼給大家講解SpringTask-Timer實(shí)現(xiàn)定時(shí)任務(wù)的相關(guān)知識(shí),感興趣的朋友一起看看吧2024-06-06

