【问题标题】:Strange output in String in Java [duplicate]Java中String中的奇怪输出[重复]
【发布时间】:2012-10-20 03:41:24
【问题描述】:

可能重复:
Concatenating null strings in Java

请在下面找到代码sn-p

String str = null;
str = str + "hi";

System.out.println(str)

以上代码的输出是nullhi

我以为输出会是hi,所以对输出有点惊讶,却找不到背后的原因。

谁能解释一下。

【问题讨论】:

  • 我只花了 5 秒钟就获得了帖子的链接。请定期使用 Google。
  • 我不确定要用于谷歌搜索的文本,所以直接在这里发布。

标签: java string


【解决方案1】:

这是因为append 方法。 + 被转换为 StringBuilderStringBuffer 附加操作。

public AbstractStringBuilder append(String str) {
if (str == null) str = "null";

public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}

下面是为您的程序生成的字节码

 0  aconst_null
 1  astore_1 [str]
 2  new java.lang.StringBuilder [16]
 5  dup
 6  aload_1 [str]
 7  invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [18]
10  invokespecial java.lang.StringBuilder(java.lang.String) [24]
13  ldc <String "hi"> [27]
15  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
18  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [33]
21  astore_1 [str]
22  getstatic java.lang.System.out : java.io.PrintStream [37]
25  aload_1 [str]
26  invokevirtual java.io.PrintStream.println(java.lang.String) : void [43]
29  return

所以你的代码实际上被转换为append(null) 然后append("hi") 这就是你得到这样的输出的原因

15.18.1. String Concatenation Operator +中也有明确记录

实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间 String 对象。为了提高重复字符串连接的性能,Java 编译器可以使用 StringBuffer 类或类似技术来减少通过评估表达式创建的中间字符串对象的数量。

【讨论】:

  • 这些都是美好而有趣的事实,但 OP 观察的真正原因不在于编译器实现细节,而在于明确指定连接运算符语义的 JLS。
  • @MarkoTopolnik 您的 cmets 总是增加我的知识。添加了来自JLS 的此类参考
【解决方案2】:

来自 JLS。

http://docs.oracle.com/javase/specs/jls/se7/html/index.html

§15.18.1。字符串连接运算符 + (reference)

如果只有一个操作数表达式是字符串类型,则对另一个操作数执行字符串转换(第 5.1.11 节)以在运行时生成字符串。

§5.1.11。字符串转换 (reference)

如果引用为空,则将其转换为字符串“null”(四个 ASCII 字符 n、u、l、l)。

【讨论】:

    【解决方案3】:

    null 是您尝试在 java 中打印空引用时打印的值。

    【讨论】:

      【解决方案4】:

      当您将不是所有字符串的值连接在一起时,那些不是字符串的值将被转换为如同String.valueOfString.valueOf(null) 是字符串"null"

      【讨论】:

      • 但是str是一个String,所以这里就不解释了。
      • null 不是字符串(实际上它不是任何对象)。
      • 您的意思是暗示编译器生成的代码动态检查是否使用String.valueOf?你的暗示是错误的:String.valueOf 总是被调用 对于+ 的所有引用类型的参数。
      • 公平点,我试图描述效果,而不是机制。
      • 如果只是说“所有操作数都像String.valueOf一样转换”,效果的描述也更简单。
      【解决方案5】:

      这是 Java 的创建者早期做出的决定。任何连接到字符串的空值都将输出为null。如果您想像您正在尝试输出日志消息,那么这种做法是有道理的:

      String personName = null;
      System.out.println("Person name is: " + personName);
      

      结果:

      人名是:null

      这种行为可以在调试时为您提供帮助,因为您知道该变量实际上是 null(而不是空字符串,例如)。

      当您尝试这样做时,他们本可以选择简单地抛出异常,但即使在执行诸如构建日志消息或异常字符串之类的操作时,也会导致很多事情中断。

      他们也可以按照您的预期完成,并将空值作为空字符串输出。这就是 .NET 框架所做的。但最终,这不是他们决定做的。

      【讨论】:

        【解决方案6】:

        在你展示的例子中 您将字符串 null 与 hi 连接,因此生成的输出是
        nullhi

        String str = null;
        str = str + "hi";
        
        System.out.println(str);
        
        
        as str=str+"hi "//shows one string is concatenating with the other
        

        所以你得到的输出是正确的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-29
          • 2012-01-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-19
          相关资源
          最近更新 更多