【问题标题】:Java String initializationJava 字符串初始化
【发布时间】:2011-03-20 05:31:25
【问题描述】:

你更喜欢哪个,为什么”

String myString = null;
if(someCondition)
   myString = "something";
else
   myString = "something else";

String myString = "";
if(someCondition)
   myString = "something";
else
   myString = "something else";

我知道可以使用三元 (? :) 运算符,但我想了解以上两个。

【问题讨论】:

  • 注意声明“String myString;”在 Java 中导致它被隐式初始化为 null。
  • @Jim:仅适用于实例和静态变量。不适用于局部变量 - 必须先明确分配它们,然后才能读取它们。
  • @Jim 跟进 Jon 的评论,如果变量没有被初始化,Java 甚至不会让你操作它,你会得到“变量 foo 可能没有被初始化”
  • 我希望后者应该在 FindBugs 中生成 Dead store to myString 警告
  • @Jon:感谢您的澄清。

标签: java conditional preferences variable-initialization


【解决方案1】:

两者都没有。相反,这个:

String myString;
if (someCondition)
   myString = "something";
else
   myString = "something else";

两个您的备选方案中,变量被初始化为一个永远不会被读取的值。它存在的事实具有误导性。

我会实际上使用条件运算符,当然 - 但除此之外,以上是更好的选择。

【讨论】:

  • 我也更喜欢这个。为什么要给 myString 一个会被替换的值?
  • +1 表示条件运算符,在这种情况下非常出色
  • 这实际上不仅仅是一种风格偏好,它确实是一个更好的解决方案。编译器能够在此处进行路径检查,并告诉您其中一个路径在使用之前是否未能初始化该值。在你初始化它的情况下,你删除了编译器来帮助你的能力。
  • @Erick:不,请参阅问题上的 cmets。
【解决方案2】:

惯用的方式是使用三元/条件运算符(JLS 15.25):

String myString = (someCondition ? "something" : "something else");

但如果您真的觉得必须这样做,您也可以使用更详细的 if-else 声明:

final String myString;
if(someCondition) {
   myString = "something";
} else {
   myString = "something else";
}

请注意,我在上面的 sn-p 中添加了 final 修饰符。如果您打算进一步重新分配变量,那么它当然不能是final,因此您可以删除修饰符,当然代码仍然可以工作。


为什么是final

上述sn-p 中final 的要点是表明if-else 构造将在所有可能的执行路径中分配给myString 一次且恰好一次。这就是提议的if-else 解决方案的主要思想:如果您只想为局部变量赋值一次,即使它可能是多种可能性之一,那么将其设为final 以增强可读性。

例如,将其与这个“替代”提案进行对比:

// DON'T DO THIS! Example only!
String myString = "something else";
if (someCondition) myString = "something";

使用此构造,您可能会分配给myString 两次,因此即使没有进一步重新分配,您也不能将final 放在这里。您也不能将 final 放入原始的 = null;= ""; 提案中,这是不推荐它们的主要原因之一。

如果您只是要在使用它之前覆盖它,那么为变量赋值是没有意义的。它会损害可读性,甚至可能隐藏错误,例如当一个执行路径无法覆盖这个“初始”值时。

参考文献


总结

  • 如果您要覆盖它,不要仅仅为了这样做而“初始化”一个局部变量
    • 让它未初始化,以便编译器可以帮助您通过指出变量在未初始化时的任何使用来识别可能的错误
    • 如果代码编译通过,那么在所有使用之前,至少一次为变量分配一个“真实”值
  • 如果不需要重新分配局部变量,则设为final以增强可读性
    • final 立即向读者保证,不再可能进行重新分配
    • 编译器可以帮助您防止出现后续重新赋值的错误
    • 如果代码可以编译,那么在所有使用之前恰好一次为变量分配一个“真实”值
  • 一般来说,您应该让编译器帮助您编写最好、最易读的代码。

【讨论】:

  • 我认为 final 与局部变量是否需要赋值没有任何关系,您的链接似乎支持这一点。你能澄清一下你的意思吗?
  • 投反对票的人请解释一下,因为我会根据反馈修改我的答案。
【解决方案3】:

初始化步骤不是必需的,可能会使未来的读者感到困惑。

我个人的看法是这种变量应该只分配一次,因此它是final关键字的完美候选。

final String myString;
if (someCondition) {
   myString = "something";
} else {
   myString = "something else";
}

请注意,myString 定义不包括赋值(因为这将禁止以后的赋值)并且在赋值之后它是只读的。这提供了健壮的代码并更清楚地显示您的意图。

还请注意,即使是单行,我也相信大括号。可能是 Perl 的一个习惯,但如果你不这样做,它总有一天会咬你。

【讨论】:

    【解决方案4】:
    String myString = "something else";
    if(someCondition) myString = "something"; // (use curly braces if you prefer)
    

    【讨论】:

      【解决方案5】:

      我更喜欢第一个,因为String myString = "" 会在池中创建额外的对象

      【讨论】:

      • 由于它是编译时已知的静态字符串,因此它将被引用到值为 "".. 的实习字符串。所以不是对象,只是一个引用。
      • 是的,但是这个实习字符串必须在字符串池中创建
      • Once... 以微不足道的代价,这几乎肯定无论如何都会发生,因为大多数 Java 程序都会接触到一个库somewhere,它有一个空的字符串。
      【解决方案6】:
      String mystring = null;
      mystring.length() 
      // Cause error
      

      上面会因为空指针导致错误。

      string myString = new String();
      myString.length()
      // will not cause error
      

      我喜欢以后再用,但我认为这是个人喜好。

      【讨论】:

      • 创建一个新字符串是没有意义和浪费的......但是使用 any 值有点毫无意义,因为该值将立即被丢弃并分配一个新值。
      • 这是真的,但完全无关;他没有在空指针上调用函数,而是立即重新分配它
      【解决方案7】:

      下面这段代码怎么样,反正他想设置点什么。

      String myString = (someCondition)  ? "something " : "else something";
      

      或者这个

      String myString = "else something"; 
      
      if (someCondition)
         myString = "something";
      

      在上述情况下,如果你 90% 确定 someCondition 始终为真。否则在声明中创建不必要的对象。期待来自 Gurus 的 cmets。

      【讨论】:

        猜你喜欢
        • 2011-03-20
        • 2014-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 2011-12-11
        相关资源
        最近更新 更多