[英]Constructor is called before non-static block?
這是我的程序:
public class Num2 {
static
{
System.out.println("static block -1");
}
int no;
Num2(int n)
{
no=n;
System.out.println("Num");
}
Num2()
{
no=0;
System.out.println("default num");
}
{
System.out.println("Non-static block of num1");
}
}
class call_by_value2 extends Num2
{
static
{
System.out.println("static block of call by value");
}
{
System.out.println("non- static block of call by value");
}
call_by_value2()
{
System.out.println("Default of call by value");
}
static void changeno(Num2 n1,Num2 n2)
{
Num2 n=new Num2();
n=n1;
n1=n2;
n2=n;
}
public static void main(String[] args)
{
System.out.println("Main method");
call_by_value2 c=new call_by_value2();
}
}
輸出為:
static block -1
static block of call by value
Main method
Non-static block of num1
default num
non- static block of call by value
Default of call by value
這是理想的輸出,因為我們知道首先調用了非靜態塊,然后調用了構造函數。但是當我修改該程序並按以下方式運行時:
public class Num2 {
static
{
System.out.println("static block -1");
}
int no;
Num2(int n)
{
no=n;
System.out.println("Num");
}
Num2()
{
no=0;
System.out.println("default num");
}
{
System.out.println("Non-static block of num1");
}
}
class call_by_value2 extends Num2
{
static
{
System.out.println("static block of call by value");
}
{
System.out.println("non- static block of call by value");
}
call_by_value2()
{
super(50);
System.out.println("Default of call by value");
}
static void changeno(Num2 n1,Num2 n2)
{
Num2 n=new Num2();
n=n1;
n1=n2;
n2=n;
}
public static void main(String[] args)
{
System.out.println("Main method");
call_by_value2 c=new call_by_value2();
}
}
現在的輸出是:
static block -1
static block of call by value
Main method
Non-static block of num1
Num
non- static block of call by value
Default of call by value
所以我的問題是,包含super()方法的callbyvalue2 class
默認構造函數是否最后運行,Num2類的參數化構造函數如何在callbyvalue2類的默認構造函數的輸出之前提供輸出?
不,這是您打個電話時發生的情況。
new Num2() ;
1)所有變量均使用默認值(0,null,false,'\\ u0000')進行初始化,包括從超類繼承的變量。
2)調用隱式或顯式超類構造函數,直到Object類為止(不允許將任何局部變量或方法返回作為參數傳遞給超類構造函數調用)。 請注意,盡管此時調用了隱式或顯式構造函數,但它們不會在內部執行任何代碼。
(如果您有一個空的構造函數,則編譯器將對no-args超類構造函數進行隱式調用,因此直到到達最頂級的超類構造函數之后,該方法才可以在方法內部執行任何操作,因為代碼的第一行每個構造函數都將是super();無論您是否放置它,如果超類沒有可用的無參數構造函數,則您必須在子類構造函數中顯式提供第一行代碼,例如super(“ string參數“);)
3)當到達頂級超類構造函數時,在該級別聲明的變量將使用其初始化程序分配(值明確分配,例如int i = 23;),無論語句在類中的什么位置聲明,並且構造函數都將在構造函數之前執行,在所有非靜態塊執行之后。
然后,第3點將沿繼承樹執行直到Num2()
示例1該第一個示例將無法編譯。
class Animal{
Animal(int){
}
}
class Dog extends Animal
{
Dog(){
// right here compiler will place an implicit call to super() ; not seen, at compile time.
// since there is no no-args constructor available in class Animal compiler will issue a warning and stop compiling. Remember that a no-args constructor is provided by default ONLY if no other constructor was provided by the programmer. In this example we have a constructor in our superclass that takes an int as argument and so we must explicitly tell the compiler to call super(24);
}
}
例子2
class Animal{
}
class Mammal extends Animal{
Mammal(int x){
}
}
class Dog extends Mammal{
Dog(){
super(24) ;
}
Dog(int x){
super(x) ;
}
}
class BullDog extends Dog{
BullDog(){
this(24) ;
}
BullDog(int x){
super(x) ;
}
}
現在,如果我們要使用no-args構造函數創建BullDog的實例,則會發生以下構造函數調用。
1個BullDog();
2頭狗(24);
3只狗(24);
4哺乳動物(24);
5這里雖然似乎什么都不存在,但請記住,編譯器提供了對超級構造函數的隱式調用,因此這里將是諸如Anima()的調用;
6這里的Animal類似乎沒有任何構造函數,但是編譯器將為以下no-args構造函數提供對super的默認調用,該調用應為Object類的no-args構造函數。
Animal(){
super() ;
}
所以6就像Object();
您現在應該了解為什么在到達Object構造函數之前,任何構造函數中的代碼都不會執行,這是因為始終會有對超類構造函數的調用作為第一行。 如果省略它,則在seperclass中最好有一個無參數的構造函數,以便它可以與編譯器默認提供的內容一起使用,否則必須顯式聲明它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.