【问题标题】:Why does empty variable declaration of type show compile error but not for null declaration?为什么类型为空的变量声明显示编译错误但不显示空声明?
【发布时间】:2013-08-03 17:27:33
【问题描述】:
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没有赋值 编译器知道s1null。那为什么不显示s1.trim() 的编译错误,比如s2

【问题讨论】:

  • 也许题外话,但如果你使用 eclipse,你会收到警告

标签: java string compiler-errors variable-assignment


【解决方案1】:

因为s2没有初始化,s1是用null初始化的

对于 Que 1:您实际上是在 null 上执行 trim() 操作,所以它会抛出应有的 NPE (NullPointerException)。

对于问题 2: 非常详细的解释见 JLS 的§4.12.5

局部变量在使用前必须显式赋值, 通过初始化或赋值,以一种可以验证的方式 由编译器使用明确赋值的规则。

【讨论】:

    【解决方案2】:
    String s2;
    

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

    String s1 = null;
    

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

    【讨论】:

    • @Keyser 是的,看我的回答。
    • @Keyser 如果它是一个实例变量,那么默认值会被自动分配(如果是 String,则为 null),在这种情况下,您不会遇到编译问题,而是 NPE。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        局部变量必须显式初始化才能使用。设置s1=null 是一种初始化,尽管相对无用。因为s2 在堆栈上并且未初始化它cannot be used

        s1 获得运行时异常,但 s2 获得编译时错误。

        【讨论】:

          【解决方案6】:

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

             String s1 = null;
          

          它保持空值。

             String s2;
          

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

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              【解决方案8】:

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

              【讨论】:

                【解决方案9】:

                让我们以 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 作者做出的决定,他们希望编译器有多聪明,同时牢记编译时间和/或其他因素的可接受值。

                【讨论】:

                  猜你喜欢
                  • 2019-11-05
                  • 2022-06-15
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2022-11-28
                  • 2016-07-03
                  • 1970-01-01
                  相关资源
                  最近更新 更多