StringBuilder.append(String str)会发生一些疯狂的事情;

时间:2012-04-24 14:48:31

标签: java

我的java项目出了问题。

以下函数应为SQL语句提供字符串:

private static String createInsertString(Pat p)
{   
    StringBuilder x = new StringBuilder();


    x.append(""  + p.getPatnr() +","+ p.getSvnr());

    java.sql.Date andat = null,gebdat;

    if(p.getAndat()==null)
        andat=null;
    else
        andat=new java.sql.Date(p.getAndat().getTimeInMillis());

    if(p.getGebdat()==null)
        gebdat=null;
    else
        gebdat=new java.sql.Date(p.getGebdat().getTimeInMillis());

    x.append("," + andat==null?"null":andat);
    x.append("," + p.getTele()==null?"null":p.getTele());
    x.append("," + p.getVName() +","+ p.getNname());
    x.append("," + p.getKk()==null?"null":p.getKk());
    x.append("," + gebdat==null?"null":gebdat);
    x.append("," + p.getAdrplzort()==null?"null":6);
    x.append("," + p.getAdrstr()==null?"null":p.getAdrstr());
    x.append("," + p.getAdrhnr()==null?"null":p.getAdrhnr());
    s.append("," + p.getReplzort()==null?"null":p.getReplzort().getPlzortnr());
    x.append("," + p.getRestr()==null?"null":p.getRestr());
    x.append("," + p.getRehnr()==null?"null":p.getRehnr());
    x.append("," + p.getLevel());
    x.append("," + p.getCon()==null?"null":p.getCon());
    x.append("," + (p.isPa()?"y":"n")+","+ (p.isLonly()?"y":"n") +","+ (p.isGest()?"y":"n"));
    x.append("," + p.getBem()==null?"null":p.getBem());
    x.append("," + (p.isKat1()?'y':'n') +","+ (p.isKat2()?'y':'n') +","+ (p.isKat3()?'y':'n'));

    System.out.println(x);

    return x.toString();
} 

输出

6,6465136nullnull,Jürgen,Wieslernullnull6nullnullnullnull,0null,n,n,nnull,n,n,n

但它应该是这样的:

6,6465136,null,null,Jürgen,Wiesler,null,null,6,null,null,null,null,0,null,n,n,n,null,n,n,n

任何想法? 我在debian(64位)上使用jdk 1.7

3 个答案:

答案 0 :(得分:11)

问题是运营商如何绑定。看看这个:

x.append("," + andat==null?"null":andat);

现在把它想象成:

x.append(("," + andat) == null ? "null" : andat);

LHS 从不将为空,因此它总是只附加andat ...而仍然转换为“null”如果引用为null,因为这是StringBuilder的默认行为。

你的代码很多比它需要的更复杂 - 效率更低。考虑将其重写为:

private static String createInsertString(Pat p)
{   
    StringBuilder x = new StringBuilder();
    java.sql.Date andat = p.andat == null ? null 
        : new java.sql.Date(p.getAndat().getTimeInMillis());
    java.sql.Date gebdat = p.getGebdat() == null ? null 
        : new java.sql.Date(p.getGebdat().getTimeInMillis());

    x.append(p.getPatnr()).append(",")
     .append(p.getSvnr()).append(",")
     .append(andat).append(",")
     .append(p.getTele()).append(",")

     // etc

    return x.toString();
}

请注意,我认为你原来有一个错误:

x.append("," + p.getVName() +","+ p.getNname());

这些意味着什么要调用两个不同的getter?

答案 1 :(得分:4)

您通过在其中加入连接来滥用.append()!这忽略了StringBuilder应该用于的所有内容。

 x.append("," + andat==null?"null":andat);

应该是

 x.append(",").append( andat == null ? "null" : andat);

这将是使您的三元运算符按预期工作的正确逻辑。

.append()会返回对StringBuilder的引用,以便您可以根据需要链接.append()个来电。

任何时候你在.append()内放置一个字符串连接,你只是创建了更多的中间String对象,这些对象占用了内存,cpu周期,然后使用更多资源,因为它们现在需要进行垃圾回收。

此外,您应该预先分配StringBuilder,其默认大小略大于您希望内容的大小,以避免浪费分配和垃圾创建。

请参阅Javadoc StringBuilder(int)构造函数。

答案 2 :(得分:3)

问题来自你的'+'。

  1. 如果您使用StringBuilder,请不要使用'+':效率不高
  2. 如果andat为null,则
  3. "," + andat==null?"null":andat会产生",null"==null?"null":andat
  4. '+'字符串连接优先于三元运算符

    当你对String使用'+'时,编译器实际上将它转换为StringBuilder(或Java5之前的StringBuffer)

    所以

    String s = a + b + c;
    

    实际上翻译为:

    String s = new StringBuilder().append(a).append(b).append(c).toString().
    

    因此,在创建其他不必要的StringBuilder时,在StringBuilder中使用+会适得其反。