4
public static void main(String[] args) {
    String s1 = null;
    String s2;
    s1.trim(); //No compile error. But run time error
    s2.trim(); //compile error.
}

s1在上面的代码中,初始化编译器知道s1is后没有赋值null。那为什么不显示s1.trim()类似的编译错误s2

4

9 回答 9

4

因为s2没有被初始化并且s1被初始化为null

对于问题 1:您实际上是在执行trim()操作null,因此它将NullPointerException按应有的方式抛出 NPE ( )。

对于问题 2: 请参阅JLS 的§4.12.5以获得非常详细的解释:

在使用局部变量之前,必须通过初始化或赋值来显式地赋予一个值,编译器可以使用明确赋值的规则对其进行验证。

于 2013-08-02T12:34:58.653 回答
2
String s2;

这是一个局部变量。局部变量没有给出默认值,您必须在使用前提供一个默认值,否则编译器会报错。您无法编译代码的原因。

String s1 = null;

您正在初始化此局部变量。所以没有编译问题,但你不能对空的东西执行修剪操作。所以你得到 NPE 这是一个运行时异常,默认情况下不能被缓存(尽管你可以)。

于 2013-08-02T12:35:38.567 回答
0

由于 s1 已初始化,编译器很高兴,尽管它可能会发出有关可能的 NullPointerException 的警告

于 2013-08-02T12:35:48.290 回答
0

1)空指针异常..因为没有对象但对空进行操作;2)没有初始化就不能使用局部变量

于 2013-08-02T12:35:48.483 回答
0

局部变量必须显式初始化才能使用。设置s1=null是一种初始化,尽管相对无用。由于s2在堆栈上且未初始化,因此无法使用

s1得到一个运行时异常,但s2得到一个编译时错误。

于 2013-08-02T12:37:34.233 回答
0

在创建字符串对象时,我们应该初始化一些值。

   String s1 = null;

它持有空值。

   String s2;

但变量 s2 为空值但未赋值。

于 2013-08-02T12:37:37.430 回答
0

这是因为 java 编译器在编译代码时会查找赋值运算符 (=)。当编译器在 s1 的情况下触发“=”符号时,它认为 s1 已初始化,而与初始化值无关。而在 s2 的情况下,编译器找不到赋值运算符,因此在词法阶段它会在错误表中创建一个条目,说明“变量 s2 可能尚未初始化”

于 2013-08-02T12:40:02.750 回答
0

Java 编译器会检查局部变量是否被初始化。如果不是,编译器会抛出错误。这是必需的,因为与实例变量不同,java 不会使用其默认值初始化局部变量。一旦变量被初始化,即使它是用 null 初始化的,编译器也不会抱怨,因为编译器假设,在程序执行过程中,变量会在某个地方用非 null 值重新初始化。编译器,无法检查在程序过程中重新初始化的值,因为该值在运行时可以是任何值。但是如果该值仍然为 null,将调用实例方法,JVM 会抛出 NullPointerException,因为它仅在运行时才知道。说得通?

于 2013-08-02T12:42:21.017 回答
0

让我们以 JLS 中的明确分配为例:

{
    int k;
    int n = 5;
    if (n > 2)
        k = 3;
    System.out.println(k);  /* k is not "definitely assigned"
                               before this statement */
}

有人可能会说编译器知道执行肯定会到达if块内部,导致赋值,k所以它应该编译得很好,但事实并非如此。

我认为这是 Java 作者做出的决定,他们希望编译器有多聪明,同时牢记编译时间和/或其他因素的可接受值。

于 2013-08-02T12:45:34.077 回答