2011-12-22 285 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; 
相关问题