java與C++變量初始化的對比

java盡力保證:全部變量在使用前都能獲得恰當的初始化html

①函數/方法局部變量的初始化

在C/C++中,變量的初始化仍是得依賴於程序員的自覺性。對於函數局部變量,編譯器不會爲基本類型賦予默認初始值,新手常常會使用未初始化的指針訪問內存,致使程序崩潰。對於類對象,編譯器將使用類的默認構造函數對對象進行初始化。而在java中,對於方法的局部變量,java以編譯時錯誤來保證變量在使用前都能獲得恰當的初始化。java

void f(){
    int i ;
    i ++ ; //Error- - i not initialized
}

儘管java編譯器也能夠爲方法的局部變量賦予一個初值,但局部變量未初始化更有多是程序員的疏忽,採用默認值反而會掩蓋這種錯誤。程序員

②類數據成員的初始化

C++程序員剛接觸到java的類時可能會很不習慣,java類的數據成員竟然能夠在定義時就初始化:編程

public class InitialValues{
boolean bool = true;
char ch = ‘x’;
int i = 999;
double d = 3.14;
Depth d = new Depth();
}

這種方式在java中稱爲指定初始化。在指定初始化以前,編譯器還會爲這些數據成員進行默認初始化,其實是把剛分配的對象內存都置零。安全

// java數據成員的默認初始化
public class InitialValues{
    boolean t;  //flase
    char c;     //[]
    short s;    //0
    byte b;   //0
    int i; //0
    long l; //0
    float f; //0.0
    double d; //0.0
}

在對象裏定義一個引用,且不將其初始化時,默認初始化爲null。這種默認初始化的實現是,在建立(new)一個對象時,在堆上對對象分配足夠的空間以後,這塊存儲空間會被清零,這樣就自動把基本類型的數據成員都設置成了默認值。默認初始化動做以後,才執行指定初始化。也就是說下面的i經歷過被初始化爲0後,再賦值爲999的過程。函數

public class InitialValues{
int i = 999;
}

java也可使用構造函數來進行初始化,但構造函數的初始化沒法阻止指定初始化和默認初始化的進行,並且老是在它們以後,纔會執行構造函數初始化。總結起來講,java中數據成員的初始化過程是:指針

  • ① 先默認初始化
  • ② 進行定義處的初始化(指定初始化)
  • ③ 構造函數初始化

C++禁止在定義數據成員時就進行指定初始化,並且C++也沒有默認初始化。有人會問,下面這段代碼不是默認初始化了嗎?code

class Test {
public:
    int i;
    double b;
    char ch;
};
int main()
{
    Test *t = new Test();
    cout << t->b; //輸出0
    cout << t->i; //輸出0
    cout << t->ch; //輸出[]
    return 0;
}

這其實是C++的默認構造函數進行的構造函數初始化。當類沒有構造函數時,編譯器會爲類聲明並實現一個默認構造函數,默認構造函數將數據成員初始化爲默認值。因此C++數據成員的初始值,只能依賴:htm

  • 成員初始化列表
  • 構造函數

成員初始化列表與java的指定初始化類似,也是在進入構造函數函數體以前,對數據成員進行的初始化。在數據成員的初始化順序上,java與C++卻是一致的,定義的順序決定了初始化的順序。對象

關於static成員的初始化

在java中不容許有static的局部變量,只可以有static的域,如static數據成員。static數據成員在對象被第一次建立時纔會被實例化,並且只實例化一次。例如:

class StaticTest{
    int _a ;
    StaticTest (int a ){
        _a = a;
        System.out.println("StaticTest("+a+")");
    }
}

class Test{
    static StaticTest st1= new StaticTest(1);
    StaticTest nonSt = new StaticTest(0);     
    static StaticTest st2= new StaticTest(2);
}

public class Main {
    public static void main(String[] args) throws Throwable {
        Test t = new Test(); //直到這個時候, st1與st2纔會被實例化
    }
}

//程序輸出
StaticTest(1)
StaticTest(2)
StaticTest(0)

從輸出能夠看出在java中,初始化順序是這樣的:先初始化靜態數據成員,再初始化非靜態數據成員。

在C++中,static數據成員必須在類以外初始化。關於C++的static,http://www.cnblogs.com/QG-whz/p/4473384.html 我之前的總結放在這裏挺合適的。

回到篇首的話。

java盡力保證:全部變量在使用前都能獲得恰當的初始化(《java編程思想》)

java在變量初始化上,普通變量以編譯錯誤、成員變量以默認初始化等手段,盡力使全部的變量在使用前均可獲得初始化,在安全性上大大強於C++。

相關文章
相關標籤/搜索