2011-12-22 246 views
4

我在這裏有一個非常基本的問題,即使它必須存在,我仍然無法找到解決方案。爲什麼Java中的單元化對象未設置爲空?

我有以下代碼:

public class Foo { 
    public static void main(String[] args) { 
     String foo; 
     if (foo != null) { 
      System.out.println("foo"); 
     } else { 
      System.out.println("foo2"); 
     } 
    } 
} 

它給了我

'變量可能尚未初始化'

。爲什麼我必須顯式指定null,並且並非所有變量都默認初始化爲null?

+2

因爲這是事物的方式是...在一流水平 –

+1

唯一的成員變量自動,如果你初始化不要明確地初始化它們;局部變量不會自動初始化。這些只是Java編程語言的規則。 – Jesper

回答

15

它可以防止你從意外使用本地變量之前,它已被明確分配。這是一個好的的事情 - 它有助於防止錯誤。對於字段(實例和靜態變量)無法完成是一件令人遺憾的事情 - 但除了最終變量之外,編譯器不知道你何時讀取它們,以及何時分配它們 - 它不能告訴你要調用方法的順序。在單一方法中,它具有更多關於流量控制的信息,因此可以爲您提供更多檢查。

如果你想一個局部變量的值是零,你爲什麼不只是明確設置爲null?這不僅讓編譯器保持高興 - 它還清楚了你的意圖。

有關明確分配的更多詳細信息,請參見chapter 16 of the Java Language Specification

下面是它如何能夠避免錯誤的例子:如果集合爲空

Iterable<String> collectionOfNames = ...; // Some method call 
String lastNameInCollection; 
for (String name : collectionOfNames) 
{ 
    lastNameInCollection = name; 
} 
System.out.println("The last name was: " + lastNameInCollection); 

應該發生什麼? 也許我們想要打印「姓氏是:null」 - 但也許我們應該做別的。上面不會編譯的事實(因爲lastNameIncollection可能不會被分配)迫使程序員考慮名稱集合爲空的情況。

+0

我認爲這不能回答這個問題。這不是爲什麼編譯器會抱怨,但爲什麼局部變量不會自動使用默認值(如類的成員)進行初始化,以及爲什麼您必須明確地執行它。 – Reboot

+2

@Reboot:不,我已經解釋了爲什麼:這是爲了避免您在給予價值之前意外使用它們。 –

+0

如果局部變量將被分配一個默認值,問題就不存在了。這就是問題:爲什麼本地變量沒有被賦予默認值?因此,解釋爲什麼編譯器阻止您使用單位值,並不能解釋爲什麼您必須手動初始化變量。 – Reboot

1

簡單的答案是:
成員局部變量不會用'null'值自動初始化。 但是類成員變量是。

此代碼將工作

public class Foo { 
    String foo; 
    public static void main(String[] args) { 
    if (foo != null) { 
     System.out.println("foo"); 
    } else { 
     System.out.println("foo2"); 
    } 
    } 
} 

或者這一個

public class Foo { 
    public static void main(String[] args) { 
    String foo = null; 
    if (foo != null) { 
     System.out.println("foo"); 
    } else { 
     System.out.println("foo2"); 
    } 
    } 
} 

如果你想獲得這個問題的完整的深刻理解考慮喬恩斯基特答案,並檢查他提供的鏈接。

1

它也可以是完全沒有必要對其進行初始化,如果它肯定是以後初始化:

String foo; 
    if (specialUseCase) { 
     foo = "this"; 
    } else { 
     foo = "that"; 
    } 
-1

局部變量不會被自動初始化,你必須明確地初始化them.Only變量初始化到成員null或默認值,即使您沒有明確初始化。如果在方法main()外面保留String foo;,則不需要初始化。

2

保留變量未初始化有時是一件好事,它允許編譯器在使用它之前檢查它是否已分配到代碼的所有可能分支中。例如,如果你有一個複雜的條件下,分配一個變量,不應該null

String variable; 
if (conditionA) { 
    if (conditionB) 
     variable = "B"; 
    else 
     variable = "A"; 
} else { 
    switch (conditionC) { 
    case 1: 
     variable = "C1"; 
     break; 
    case 2: 
     variable = "C2"; 
     break; 
    default: 
     variable = "CD"; 
     break; 
    } 
} 
System.out.println(variable.length()); 

如果你忘記了變量的一個分支分配,編譯器會抱怨。既然你知道,你永遠不會分配null,你可以安全地使用該變量而不檢查它是否爲null。如果您在定義null初始化變量,你忘了設置變量的值,編譯器將無法檢查這一點,你可以得到一個NullPointerException

String variable = null; 
if (conditionA) 
    variable = "A"; 
// NullPointerException if conditionA is false, not check by compiler 
System.out.println(variable.length()); 

變量也可能是最後的,在這種情況下,它只能分配一次。如果你想用默認值初始化它,它會已經被分配的,不能被重新分配:

final int variable; 
if (condition) 
    variable = 1; 
else 
    variable = 2; 
相關問題