java中构造方法和方法全面解析
java中構造方法和方法全面解析?
??????????我相信大多說人都對構造方法、方法不陌生,而且很了解,但我也相信有很多像我這樣的沒有一個很好很清晰很全面的認識,今天就把它整理如下,希望能給大家帶來點方便與幫助,也希望大家多多討論。
??????????構造方法和方法的區別:??????????
?????構造方法要與類名相同,無返回類型,在類初始化的時候調用。?
?????方法最好與類名不同,對象調用,靜態方法可用類名.方法().
?????構造器和方法在下面三個方面區別:修飾符,返回值,命名。
???????1。和方法一樣,構造器可以有任何訪問的修飾:?public,?protected,?private或者沒有修飾(通常被package?和?friendly調用).?不同于方法的是,構造器不能有以下非訪問性質的修飾:?abstract,?final,?native,?static,?或者?synchronized。?
????????2。返回類型也是非常重要的。方法能返回任何類型的值或者無返回值(void),構造器沒有返回值,也不需要void。?
????????3。兩者的命名。構造器使用和類相同的名字,而方法則不同。按照習慣,方法通常用小寫字母開始,而構造器通常用大寫字母開始。構造器通常是一個名詞,因為它和類名相同;而方法通常更接近動詞,因為它說明一個操作。
????構造方法和方法中this和supper的用法區別:?
???
????"this"的用法?
????構造器和方法使用關鍵字this有很大的區別。方法引用this指向正在執行方法的類的實例。靜態方法不能使用this關鍵字,因為靜態方法不屬于類的實??例,所以this也就沒有什么東西去指向。構造器的this指向同一個類中,不同參數列表的另外一個構造器,我們看看下面的代碼:?
package?com.dr.gouzao;
public?class?Platypus?{
????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();
????????System.out.println(p1.name?+?"----"?+?p2.name);
????}
}
在上面的代碼中,有2個不同參數列表的構造器。第一個構造器,給類的成員name賦值,第二個構造器,調用第一個構造器,給成員變量name一個初始值?"John/Mary?Doe".?
在構造器中,如果要使用關鍵字this,那么,必須放在第一行,如果不這樣,將導致一個編譯錯誤。
在一個構造方法中只能調用一次其它的構造方法,并且調用構造方法的語句必須是第一條語句。
?
???"super"的用法?
???構造器和方法,都用關鍵字super指向超類,但是用的方法不一樣。方法用這個關鍵字去執行被重載的超類中的方法。看下面的例子:
package?com.dr.gouzao;
class?Mammal?{
????void?getBirthInfo()?{
????????System.out.println("born?alive.");
????}
}
class?Platypus1?extends?Mammal?{
????void?getBirthInfo()?{
????????System.out.println("hatch?from?eggs");
????????System.out.print("a?mammal?normally?is?");
????????super.getBirthInfo();
????}
????}
在上面的例子中,使用super.getBirthInfo()去調用超類Mammal中被重載的方法。?
構造器使用super去調用超類中的構造器。而且這行代碼必須放在第一行,否則編譯將出錯??聪旅娴睦?#xff1a;
public?class?SuperClassDemo?{
????SuperClassDemo()?{
????}
}
class?Child?extends?SuperClassDemo?{
????Child()?{
????????super();
????}
}
在上面這個沒有什么實際意義的例子中,構造器?Child()包含了?super,它的作用就是將超類中的構造器SuperClassDemo實例化,并加到?Child類中。?
編譯器自動加入代碼?,當我們寫一個沒有構造器的類,編譯的時候,編譯器會自動加上一個不帶參數的構造器。
現在具體介紹一下構造方法的幾種用法:
類的繼承機制使得子類可以使用父類的功能(即代碼),并且子類也具有父類的類型。下面介紹類在繼承關系上的初始化的順序問題。?
示例1:
class?SuperClass?
{?
SuperClass()?
{?
System.out.println("SuperClass?constructor");?
}?
}?
public?class?SubClass?extends?SuperClass?
{?
SubClass()?
{?
System.out.println("SubClass?constructor");?
}?
public?static?void?main(String[]?args)?
{?
SubClass?sub?=?new?SubClass();?
}?
}?
輸出結果:?SuperClass?constructor?
????????????SubClass?constructor?
在子類中只實例化了一個子類對象。從輸出結果上看,程序并不是一開始就運行自己的構造方法,而是先運行其父類的默認構造方法。注意:程序自動調用其父類的默認構造方法。
實例2
class?SuperClass?
{?
SuperClass(String?str)?
{?
System.out.println("Super?with?a?string.");?
}?
}?
public?class?SubClass?extends?SuperClass?
{?
SubClass(String?str)?
{?
System.out.println("Sub?with?a?string.");?
}?
public?static?void?main(String[]?args)?
{?
SubClass?sub?=?new?SubClass("sub");?
}?
}?
?
在JDK下編譯此程序不能成功。正如上例中說的:程序在初始化子類時先要尋找其父類的默認構造方法,結果沒找到,那么編譯自然不能通過。?
解決這個問題有兩個辦法:?
1.在父類中增加一個默認構造方法。?
2.在子類的構造方法中增加一條語句:super(str);?且必須在第一句。?
這兩種方法都能使此程序通過編譯,但就本程序來說運行結果卻不相同。?
第1種方法的運行結果是:
Sub?with?a?string.?
第2種方法的運行結果是:?
????Super?with?a?string.?
????Sub?with?a?string.
?
第2種解決方法實際上是指定編譯器不要尋找父類的默認構造方法,而是去尋找帶一個字符串為參數的構造方法。?
下面介紹對象的初始化順序問題。?
示例3:?
class?One?
{?
One(String?str)?
{?
System.out.println(str);?
}?
}?
class?Two?
{?
One?one_1?=?new?One("one-1");?
One?one_2?=?new?One("one-2");?
One?one_3?=?new?One("one-3");?
Two(String?str)?
{?
System.out.println(str);?
}?
}?
public?class?Test?
{?
public?static?void?main(String[]?args)?
{?
System.out.println("Test?main()?start");?
Two?two?=?new?Two("two");?
}?
}?
?
輸出結果:?
Test?main()?start...?
one-1?
one-2?
one-3?
two?
在main()方法中實例化了一個Two類的對象。但程序在初始化Two類的對象時,并非先調用Two類的構造方法,而是先初始化Two類的成員變量。這里Two類有3個成員變量,它們都是One類的對象,所以要先調用3次One類的相應的構造方法。最后在初始化Two類的對象。
?即在創建對象時,對象所在類的所有數據成員會首先進行初始化,如果其中的成員變量有對象,那么它們也會按照順序執行初始化工作。在所有類成員初始化完成后,才調用對象所在類的構造方法創建對象。構造方法作用就是初始化。?
示例4:
?
class?One?
{?
One(String?str)?
{?
System.out.println(str);?
}?
}?
class?Two?
{?
One?one_1?=?new?One("one-1");?
One?one_2?=?new?One("one-2");?
static?One?one_3?=?new?One("one-3");?
Two(String?str)?
{?
System.out.println(str);?
}?
}?
public?class?Test?
{?
public?static?void?main(String[]?args)?
{?
System.out.println("Test?main()?start");?
Two?two_1?=?new?Two("two-1");?
System.out.println("------------");?
Two?two_2?=?new?Two("two-2");?
}?
}?
輸出結果:?
Test?main()?start...?
one-3?
one-1?
one-2?
two-1?
------------?
one-1?
one-2?
two-2?
如果一個類中有靜態對象,那么它會在非靜態對象前初始化,但只初始化一次。非靜態對象每次調用時都要初始化。
實例5
class?One?
{?
One(String?str)?
{?
System.out.println(str);?
}?
}?
class?Two?
{?
One?one_1?=?new?One("one-1");?
One?one_2?=?new?One("one-2");?
static?One?one_3?=?new?One("one-3");?
Two(String?str)?
{?
System.out.println(str);?
}?
3?
}?
public?class?Test?
{?
static?Two?two_3?=?new?Two("two-3");?
public?static?void?main(String[]?args)?
{?
System.out.println("Test?main()?start");?
Two?two_1?=?new?Two("two-1");?
System.out.println("------------");?
Two?two_2?=?new?Two("two-2");?
}?
}?
輸出結果:?
one-3?
one-1?
one-2?
two-3?
Test?main()?start...?
one-1?
one-2?
two-1?
------------?
one-1?
one-2?
two-2?
程序中主類的靜態變量會在main()方法執行前初始化。結果中只輸出了一次one-3,這也說明:如果一個類中有靜態對象,那么它會在非靜態對象前初始化,但只初始化一次。非靜態對象每次調用時都要初始化。?
實例6
class?One?
{?
One(String?str)?
{?
System.out.println(str);?
}?
}?
class?Two?
{?
static?int?i?=?0;?
One?one_1?=?new?One("one-1");?
static?One?one_2?=?new?One("one-2");?
static?One?one_3?=?new?One("one-3");?
Two(String?str)?
{?
System.out.println(str);?
}?
}?
public?class?Test?
{?
public?static?void?main(String[]?args)?
{?
System.out.println("Test?main()?start");?
System.out.println("Two.i?=?"??Two.i);?
}?
}?
輸出結果:?
Test?main()?start...?
one-2?
one-3?
Two.i?=?0?
不僅第1次創建對象時,類中所有的靜態變量要初始化,第1次訪問類中的靜態變量(沒有創建對象)時,該類中所有的靜態變量也要按照它們在類中排列的順序初始化。
?
初始化的順序包括構造方法調用的順序如下:?
1.主類的靜態成員首先初始化。?
2.主類的超類的構造方法按照從最高到最低的順序被調用。?
3.主類的非靜態對象(變量)初始化。?
4.調用主類的構造方法。?
總結
以上是生活随笔為你收集整理的java中构造方法和方法全面解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中print、printf、pr
- 下一篇: 全面解析Java中的String数据类型