什么是Java構造方法?Java構造方法怎么定義?Java構造方法怎么調用?Java構造方法有什么作用?Java構造方法可以重載嗎?接下來學習一下。
Java構造方法是類中特殊的方法,通過調用構造方法來完成對象的創建,以及對象屬性的初始化操作。
Java構造方法怎么定義,請看以下的語法格式:
[修飾符列表] 構造方法名(形式參數列表){
構造方法體;
}
● 構造方法名和類名一致。
● 構造方法用來創建對象,以及完成屬性初始化操作。
● 構造方法返回值類型不需要寫,寫上就報錯,包括void也不能寫。
● 構造方法的返回值類型實際上是當前類的類型。
● 一個類中可以定義多個構造方法,這些構造方法構成方法重載。
怎么調用構造方法呢,語法格式是:new 構造方法名(實際參數列表);接下來,看以下代碼:
圖9-12:調用無參數構造方法
以上程序運行結果如下圖所示:
圖9-13:調用無參數構造方法的運行結果
以上程序的輸出結果中雖然第一行看不懂,但起碼說明程序是能夠正常執行的。我們看到以上Date類當中的代碼,并沒有發現任何構造方法,為什么可以調用呢?接下來我們來測試一下,把構造方法顯示的定義出來:
public class Date {
int year; //年
int month; //月
int day; //日
//構造方法(無參數構造方法)
public Date(){
System.out.println("Date類無參數構造方法執行");
}
}
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
new Date();
System.out.println("main over");
}
}
運行結果如下圖所示:
圖9-14:測試無參數構造方法
通過以上程序執行結果確實看到了“new Date()”確實調用了Date類當中的無參數構造方法。再看以下程序:
public class Date {
int year; //年
int month; //月
int day; //日
//構造方法(有參數構造方法)
public Date(int year){
System.out.println("帶有參數year的構造方法");
}
}
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
new Date();
System.out.println("main over");
}
}
編譯報錯了,錯誤信息如下圖所示:
圖9-15:編譯器錯誤信息提示
通過以上的測試,得出這樣一個結論(這是java中語法的規定,記住就行):當一個類沒有顯示的定義任何構造方法的時候,系統默認提供無參數構造方法,當顯示的定義構造方法之后,系統則不再提供無參數構造方法。無參數構造方法又叫做缺省構造器,或者默認構造方法。一般在開發中為了方便編程,建議程序員手動的將無參數構造方法寫上,因為不寫無參數構造方法的時候,這個默認的構造方法很有可能就不存在了,另外也是因為無參數構造方法使用的頻率較高。例如以下代碼:
public class Date {
int year; //年
int month; //月
int day; //日
//構造方法(無參數構造方法)
public Date(){
System.out.println("Date類無參數構造方法執行");
}
//構造方法(有參數構造方法)
public Date(int year1){
System.out.println("帶有參數year的構造方法");
}
//構造方法(有參數構造方法)
public Date(int year1 , int month1){
System.out.println("帶有參數year,month的構造方法");
}
//構造方法(有參數構造方法)
public Date(int year1 , int month1 , int day1){
System.out.println("帶有參數year,month,day的構造方法");
}
}
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
new Date();
new Date(2008);
new Date(2008 , 8);
new Date(2008 , 8 , 8);
System.out.println("main over");
}
}
運行結果如下圖所示:
圖9-16:調用所有構造方法
通過以上的測試可以看出一個類當中可以定義多個構造方法,構造方法是支持重載機制的,具體調用哪個構造方法,那要看調用的時候傳遞的實際參數列表符合哪個構造方法了。構造方法雖然在返回值類型方面不寫任何類型,但它執行結束之后實際上會返回該對象在堆內存當中的內存地址,這個時候可以定義變量接收對象的內存地址,這個變量就是之前所學的“引用”,請看以下代碼:
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
Date time1 = new Date();
System.out.println(time1);
Date time2 = new Date(2008);
System.out.println(time2);
Date time3 = new Date(2008 , 8);
System.out.println(time3);
Date time4 = new Date(2008 , 8 , 8);
System.out.println(time4);
System.out.println("main over");
}
}
運行結果如下圖所示:
圖9-17:構造方法的返回值
以上程序中time1,time2,time3,time4都是引用,輸出這些引用的結果是“Date@xxxxx”,對于這個結果目前可以把它等同看做是對象的內存地址(嚴格來說不是真實的對象內存地址)。通過這個引用就可以訪問對象的內存了,例如以下代碼:
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
Date time1 = new Date();
System.out.println(time1.year + "年" + time1.month + "月" + time1.day + "日");
Date time2 = new Date(2008);
System.out.println(time2.year + "年" + time2.month + "月" + time2.day + "日");
Date time3 = new Date(2008 , 8);
System.out.println(time3.year + "年" + time3.month + "月" + time3.day + "日");
Date time4 = new Date(2008 , 8 , 8);
System.out.println(time4.year + "年" + time4.month + "月" + time4.day + "日");
System.out.println("main over");
}
}
運行結果如下圖所示:
圖9-18:通過“引用”訪問屬性
為什么無論通過哪個構造方法創建Date對象,最終的結果都是“0年0月0日”呢?這是因為所有的構造方法在執行過程中沒有給對象的屬性手動賦值,系統則自動賦默認值,實際上大部分情況下我們需要在構造方法中手動的給屬性賦值,這本來就是構造方法的主要的職責,要不然重載多次構造方法就沒有意義了,以上的代碼應該這樣寫,請看:
public class Date {
int year; //年
int month; //月
int day; //日
public Date(){
}
public Date(int year1){
year = year1;
}
public Date(int year1 , int month1){
year = year1;
month = month1;
}
public Date(int year1 , int month1 , int day1){
year = year1;
month = month1;
day = day1;
}
}
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
Date time1 = new Date();
System.out.println(time1.year + "年" + time1.month + "月" + time1.day + "日");
Date time2 = new Date(2008);
System.out.println(time2.year + "年" + time2.month + "月" + time2.day + "日");
Date time3 = new Date(2008 , 8);
System.out.println(time3.year + "年" + time3.month + "月" + time3.day + "日");
Date time4 = new Date(2008 , 8 , 8);
System.out.println(time4.year + "年" + time4.month + "月" + time4.day + "日");
System.out.println("main over");
}
}
運行結果如下圖所示:
圖9-19:通過構造方法給屬性賦值
為什么第一個日期輸出的是“0年0月0日”?這是因為調用的是無參數構造方法創建的第一個日期對象,在無參數構造方法中沒有給屬性賦值,則系統賦默認值,所以年月日都是0。那為什么第二個日期輸出的是“2008年0月0日”呢?這是因為調用的是“public Date(int year1){ year = year1; }”構造方法創建的第二個日期對象,在這個構造方法當中只是顯示的給Date對象的year屬性賦值,month和day仍然是系統賦默認值,所以month和day都是0。第三個日期對象是“2008年8月8日”,這是因為在這個對應的構造方法中顯示的為year,month,day三個屬性都賦值了。在編寫以上構造方法的時候需要注意變量名的問題,請看下圖:
圖9-20:java遵循就近原則
通過以上內容的學習得知,構造方法的作用是專門用來創建對象同時給屬性賦值的,它的語法很簡單,比普通方法還要簡單,因為構造方法名和類名一致,還不需要寫返回值類型,使用new就可以調用了。在一個類當中可以同時定義多個構造方法,它們之間構成重載關系。這樣就做到了在java中你想要什么就new什么,每一次new都會在堆內存中創建對象,并且對象內部的實例變量被初始化了。
一定要注意,實例變量沒有手動賦值的時候系統會默認賦值,但不管是手動賦值還是系統賦默認值,都是在構造方法執行的時候才會進行賦值操作,類加載的時候并不會初始化實例變量的空間,那是因為實例變量是對象級別的變量,沒有對象,哪來實例變量,這也是為什么實例變量不能采用“類名”去訪問的原因。
public class DateTest {
public static void main(String[] args) {
System.out.println(Date.year);
}
}
編譯報錯了:
圖9-21:實例變量不能直接采用“類名”訪問