【问题标题】:StringBuilder appends null as "null"StringBuilder 将 null 附加为“null”
【发布时间】:2013-06-23 07:55:26
【问题描述】:

怎么会?

    StringBuilder sb = new StringBuilder();

    sb.append("Hello");
    sb.append((String)null);
    sb.append(" World!");
    Log.d("Test", sb.toString());

生产

06-25 18:24:24.354: D/Test(20740): Hellonull World!

我希望附加 null 字符串根本不会附加!
顺便说一句,String 的强制转换是必要的,因为StringBuilder.append() 有很多重载版本。

我简化了我的代码来说明这一点,在我的代码中有一个返回字符串的方法

public String getString() { ... }
...
sb.append(getString());
...

getString() 有时会返回null;现在如果我想使用StringBuilder,我必须测试它!!!!

此外,让我们在这里澄清我的问题:我怎样才能让StringBuilder.append() 以一种优雅的方式接受一个空字符串,而不是将其转换为文字字符串“null”。
优雅我的意思是我不想得到字符串,测试它是否是null,然后才附加它。我正在寻找一个优雅的oneliner。

【问题讨论】:

标签: java android stringbuilder


【解决方案1】:
How come?

它的clearly written in docs

String 参数的字符按顺序附加,该序列的长度增加了参数的长度。如果 str 为 null,则附加四个字符“null”。

所以请在追加前进行空检查。

【讨论】:

  • 好的,文档里有写。但是,难道只有我一个人很反直觉吗?我了解到空字符串是不存在的字符串。如果不展开讨论,我就是不明白他们为什么那样做。现在我正用头撞桌子。
  • 我认为您混淆了 null 和空字符串。正如你所说的(String)null是一个不存在的String,在String域中用“null”表示。另一方面,空字符串“”不出所料地具有“”表示。当您调试或打印某个 String 变量时,您希望实际看到它指向 null,所以这是有道理的。
  • @LastFreeNickname 不是真的,当字符串是 null 时,我不想/期望什么也看不见。如果我使用调试器,我想检查变量并将其值视为null。好像不久前,在代数课上,教授说有一个特殊的符号来表示一个空集,一个完全没有元素的集合,它类似于一个空字符串。为空字符串显示某些内容会破坏与 null 的相同定义的一致性。但这是为打翻的牛奶而哭泣,希望有一天我能知道原因。
【解决方案2】:

就是这样。 null 附加为 "null"。同样,当您使用System.out.println(null) 打印null 时,您会打印"null"

避免这种情况的方法是返回字符串getString() 的方法检查null

public String getString() {
    ...
    if (result == null) {
        return "";
    }
}

【讨论】:

    【解决方案3】:

    它的行为是这样的,因为null 并不是你想象的空的String。空的 String 将是 new String("");。基本上append() 方法会附加"null",如果它获得null 值作为参数。

    【讨论】:

    • 我不是说“空字符串”我说的是“一个不存在的字符串”
    【解决方案4】:

    编辑
    我的 previous answer 没有反映 OP 要求的 StringBuilder 此类行为的适当原因。感谢@Stephen C 指出

    我希望附加一个空字符串根本不会附加!

    但它正在附加。 StringBuilder 的这种行为的原因隐藏在 append(Object obj) 方法的实现细节中,该方法将我们带到 AbstractStringBuilder#append(String str) 方法,其定义如下:

    public AbstractStringBuilder append(String str) {
        if (str == null) str = "null"; -->(1)
        //.......
        return this;
    }
    

    它明确指出如果输入String为null,则将其更改为字符串文字“null”,然后进一步处理。

    如何让 StringBuilder.append() 以优雅的方式接受空字符串,而不是将其转换为文字字符串“null”。

    您需要明确检查给定的String 是否为null,然后继续。例如:

    String s = getString();
    StringBuffer buf = new StringBuffer();
    //Suppose you want "Hello "<value of s>" world"
    buf.append("Hello ");
    buf.append(s==null?" world" : s+" world");
    

    【讨论】:

    • 严格来说,JLS 对此并不明确。 JLS 实际上是指定“+”运算符的语义。您可能会争辩说,StringBuilder.append(null) 实现了所需的行为是一个方便的巧合。 (我敢肯定这不是巧合,但你明白我的意思......)
    【解决方案5】:

    AbstractStringBuilder 类通过String.valueOf(obj) 方法附加一个对象,该方法又将 NULL 转换为字符串文字“null”。因此,这里没有内置的方法可以帮助您。正如其他人建议的那样,您必须在 append 方法中使用三元运算符或编写实用方法来处理它。

    【讨论】:

      【解决方案6】:

      这对你有用

      public static String getString(StringBuilder sb, String str) {
          return sb.append(str == null ? "" : str).toString();
      }
      

      【讨论】:

        【解决方案7】:

        写一个实用方法怎么样

        public static void appendString(StringBuilder sb, String st) {
            sb.append(st == null ? "" : st);
        }
        

        或者这个三元运算符非常好用。

        【讨论】:

          【解决方案8】:
          String nullString = null;
          StringBuilder sb = new StringBuilder();
          sb.append("Hello");
          if (nullString != null) sb.append(nullString);
          sb.append(" World!");
          Log.d("Test", sb.toString());
          

          那里!我在一行中做到了:)

          【讨论】:

          • :-) 毫无疑问它非常优雅 :-)
          【解决方案9】:

          一行?

          sb.append((getString()!=null)?getString():"");
          

          完成。但是没有意义,因为必须两次调用getString()

          按照建议在getString() 方法中构建检查

          【讨论】:

            【解决方案10】:

            你也可以为StringBuilder编写装饰器,它可以检查你想要的任何东西:

            class NotNullStringBuilderDecorator {
            
                private StringBuilder builder;
            
                public NotNullStringBuilderDecorator() {
                    this.builder = new StringBuilder();
                }
            
                public NotNullStringBuilderDecorator append(CharSequence charSequence) {
                    if (charSequence != null) {
                        builder.append(charSequence);
                    }
            
                    return this;
                }
            
                public NotNullStringBuilderDecorator append(char c) {
                    builder.append(c);
            
                    return this;
                }
            
                //Other methods if you want
            
                @Override
                public String toString() {
                    return builder.toString();
                }
            }
            

            使用示例:

            NotNullStringBuilderDecorator sb = new NotNullStringBuilderDecorator();
            sb.append("Hello");
            sb.append((String) null);
            sb.append(" World!");
            
            System.out.println(sb.toString());
            

            使用此解决方案,您无需更改 POJO 类。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-09-22
              • 1970-01-01
              • 2011-12-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-15
              相关资源
              最近更新 更多