understanding constructors
--How constructors differ from methods
By Robert Nielsen, JavaWorld.com, 10/13/00
[譯] 馬嘉楠 2007.04.20
key words:
constructor 構(gòu)造函數(shù) method 方法 instance 實(shí)例
object 對(duì)象 modifier 修飾符 return type 返回類(lèi)型
static method 靜態(tài)方法 superclass 超類(lèi) Inheritance 繼承
platypus 鴨嘴獸
我們說(shuō)一個(gè)構(gòu)造函數(shù)是方法就好比說(shuō)澳洲鴨嘴獸是另一個(gè)哺乳動(dòng)物一樣。 為了了解鴨嘴獸,知道其與其他的哺乳動(dòng)物的差別對(duì)我們來(lái)說(shuō)非常重要。同理,了解構(gòu)造函數(shù),知道構(gòu)造函數(shù)與其他方法的區(qū)別對(duì)我們同樣重要。對(duì)于任何學(xué)習(xí)Java,尤其是為了獲得資格證書(shū)的學(xué)生來(lái)說(shuō),都需要知道這些區(qū)別。在這篇文章中,我將會(huì)一一道來(lái)。在文章結(jié)尾,Table1 總結(jié)了constructor(構(gòu)造函數(shù))和method(方法)的重要區(qū)別。
Purpose and Function (目的與功能)
構(gòu)造函數(shù)都有一個(gè)目的:創(chuàng)建一個(gè)類(lèi)的實(shí)例。也可以叫做創(chuàng)建一個(gè)對(duì)象,如下:
相比之下,方法(method)的目的顯得更為普通. 一個(gè)方法的基本功能就是為了執(zhí)行Java的代碼.
Signature differences(簽名區(qū)別)(Signature 不知道怎么翻譯好)
構(gòu)造函數(shù)(constructors)和方法(methods)在以下三個(gè)方面存在差別:
· 修飾符 (modifiers)
· 返回類(lèi)型(return type)
· 名字 (name)
像方法一樣,構(gòu)造函數(shù)可以有任意一種訪問(wèn)修飾符(access modifiers):公共的(public),保護(hù)的(protected),私有的(private)或者沒(méi)有(常被稱(chēng)為package或者friendly)。不同于方法的是,構(gòu)造函數(shù)只能被訪問(wèn)修飾符進(jìn)行限定。因此,構(gòu)造函數(shù)不能是abstract, static, final, natice or synchronized的。
兩者的返回類(lèi)型(return type)也是截然不同的。方法可以擁有任何有效的返回類(lèi)型,或者方法沒(méi)有返回值,這種情況下方法的返回類(lèi)型為void。構(gòu)造函數(shù)沒(méi)有返回類(lèi)型,也沒(méi)有void。
最后,構(gòu)造函數(shù)和方法在取名方面也有很大的不同。構(gòu)造函數(shù)名字與其類(lèi)名(class name)相同;按照慣例,方法使用其他與類(lèi)名不相同的名字。如果Java程序員遵循通常慣例,方法名將會(huì)以小寫(xiě)字母開(kāi)頭,構(gòu)造函數(shù)名字以大寫(xiě)字母開(kāi)頭。并且,因?yàn)榕c類(lèi)名相同,構(gòu)造函數(shù)名字通常是個(gè)名詞,方法名字是個(gè)動(dòng)詞。
The use of "this" (this的使用)
構(gòu)造函數(shù)和方法使用關(guān)鍵字 this 差別很大。
方法中的 this 指的是執(zhí)行該方法的類(lèi)的實(shí)例(instance)。靜態(tài)方法(static method)不使用 this 。因?yàn)殪o態(tài)方法不屬于任何一個(gè)類(lèi)的實(shí)例,所以 this 無(wú)所指向。靜態(tài)方法總體上屬于一個(gè)類(lèi)而非一個(gè)類(lèi)的實(shí)例。
構(gòu)造函數(shù)中的 this 指的是,在同一個(gè)類(lèi)中擁有不同的參數(shù)列表的另一個(gè)構(gòu)造函數(shù)。代碼如下:
String name;
Platypus(String input) {
name = input;
}
Platypus() {
this("John/Mary Doe");
}
public static void main(String args[]) {
Platypus p1 = new Platypus("digger");
Platypus p2 = new Platypus();
}
}
在代碼中,有兩個(gè)構(gòu)造函數(shù)。
第一個(gè)構(gòu)造函數(shù)通過(guò)一個(gè)String參數(shù)input給name進(jìn)行賦值。
第二個(gè)構(gòu)造函數(shù)沒(méi)有參數(shù),通過(guò)默認(rèn)的名字"John/Mary Doe"來(lái)調(diào)用第一個(gè)構(gòu)造函數(shù)。
如果在構(gòu)造函數(shù)中使用 this,則必須在構(gòu)造函數(shù)的第一行代碼當(dāng)中,否則編譯器會(huì)報(bào)錯(cuò)。
注:在我這里的報(bào)錯(cuò)信息為 Constructor call must be the first statement in a constructor。
The use of "super"(super的使用)
方法和構(gòu)造函數(shù)使用 super 的時(shí)候,指的都是超類(lèi)(superclass),但也有所不同。
方法中使用 super 將會(huì)執(zhí)行超類(lèi)中被覆蓋的方法,如下所示:
void getBirthInfo() {
System.out.println("born alive.");
}
}
class Platypus extends Mammal {
void getBirthInfo() {
System.out.println("hatch from eggs");
System.out.print("a mammal normally is ");
super.getBirthInfo();
}
}
在上面代碼中,super.getBirthInfo() 將會(huì)調(diào)用超類(lèi) Mammal 中被覆蓋的方法 getBirthInfo().
構(gòu)造函數(shù)中使用 super 將會(huì)調(diào)用超類(lèi)中的構(gòu)造函數(shù)。
如果在構(gòu)造函數(shù)中使用 super,則必須在構(gòu)造函數(shù)的第一行代碼當(dāng)中,否則編譯器會(huì)報(bào)錯(cuò)。
注:在我這里的報(bào)錯(cuò)信息為 Constructor call must be the first statement in a constructor。
代碼如下:
SuperClassDemo() {}
}
class Child extends SuperClassDemo {
Child() {
super();
}
}
Complier -- supplied code(編譯器提供的代碼)
當(dāng)編譯器自動(dòng)為構(gòu)造函數(shù)提供代碼的時(shí)候,Java初學(xué)者可能會(huì)感到困惑。如果你的類(lèi)中沒(méi)有構(gòu)造函數(shù),編譯器將會(huì)為你自動(dòng)提供一個(gè)沒(méi)有參數(shù)的構(gòu)造函數(shù)。如果你的代碼如下:
功能上它等同于如下代碼:
Example() {}
}
如果在你的構(gòu)造函數(shù)的第一行代碼當(dāng)中沒(méi)有使用 super,那么編譯器會(huì)自動(dòng)為你提供代碼,插入 super。
如果你的代碼如下:
TestConstructors() {}
}
功能上它等同于如下代碼:
TestConstructors() {
super();
}
}
初學(xué)者可能會(huì)有疑問(wèn):TestConstructors 并沒(méi)有繼承任何類(lèi),為什么它會(huì)調(diào)用父類(lèi)的構(gòu)造函數(shù)呢?
答案是:在 Java 中如果沒(méi)有顯示的繼承一個(gè)類(lèi),則默認(rèn)為繼承自 Object 類(lèi)。
如果沒(méi)有顯示的聲明一個(gè)構(gòu)造函數(shù),編譯器自動(dòng)提供一個(gè)沒(méi)有參數(shù)的構(gòu)造函數(shù);如果一個(gè)構(gòu)造函數(shù)沒(méi)有顯示的 super 調(diào)用,編譯器自動(dòng)提供一個(gè)沒(méi)有參數(shù)的 super 調(diào)用。所以下面的兩段代碼在功能上是等價(jià)的:
和
Example() {
super();
}
}
Inheritance(繼承)
下面情況有什么不對(duì)?
律師閱讀類(lèi)A的遺囑。所有家庭成員圍坐在大會(huì)議桌旁,并且有些人在輕聲嗚咽。律師說(shuō)到:“我,類(lèi)A,頭腦清楚身體健康,將我所有的構(gòu)造函數(shù)留給我的孩子”。
問(wèn)題是構(gòu)造函數(shù)不是通過(guò)繼承得到的。然而幸運(yùn)的是,子類(lèi)可以自動(dòng)的繼承父類(lèi)所有的方法,所以子類(lèi)并不是一無(wú)所有。
記住:Java 方法可以通過(guò)繼承得到,而構(gòu)造函數(shù)不行。看下面代碼:
public void sayHi {
system.out.println("Hi");
}
Example() {}
}
public class SubClass extends Example {
}
類(lèi) SubClass 自動(dòng)繼承父類(lèi)的 sayHi 方法。然而,構(gòu)造函數(shù) Example() 不會(huì)被類(lèi) SubClass 所繼承。
Summarizing the differences
構(gòu)造函數(shù)與方法的區(qū)別就像鴨嘴獸與典型的哺乳動(dòng)物一樣。尤其是在目的(purpose),簽名(signature),和 this 與 super 的使用方面。另外,在繼承和編譯器提供代碼方面也有很大差異。記住所有的區(qū)別可能會(huì)非常辛苦,所以下面提供的一個(gè)表格,簡(jiǎn)單的概括了重要的差異方面。
Topic | Constructors | Methods |
---|---|---|
Purpose | Create an instance of a class | Group Java statements |
Modifiers | Cannot be abstract, final, native, static, or synchronized | Can be abstract, final, native, static, or synchronized |
Return type | No return type, not even void | void or a valid return type |
Name | Same name as the class (first letter is capitalized by convention) -- usually a noun | Any name except the class. Method names begin with a lowercase letter by convention -- usually the name of an action |
this | Refers to another constructor in the same class. If used, it must be the first line of the constructor | Refers to an instance of the owning class. Cannot be used by static methods |
super | Calls the constructor of the parent class. If used, must be the first line of the constructor | Calls an overridden method in the parent class |
Inheritance | Constructors are not inherited | Methods are inherited |
Compiler automatically supplies a default constructor | If the class has no constructor, a no-argument constructor is automatically supplied | Does not apply |
Compiler automatically supplies a default call to the superclass constructor | If the constructor makes no zero-or-more argument calls to super, a no-argument call to super is made | Does not apply |
原文:http://www.javaworld.com/jw-10-2000/jw-1013-constructors.html
馬嘉楠
jianan.ma@gmail.com