2

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を使用しています

4

3 に答える 3

11

問題は、オペレーターがどのようにバインドするかです。これを見てください:

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

次のように考えてください。

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

LHS が null になることは決してないため、常に追加するだけで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());

これらが 2 つの異なるゲッターを呼び出すことを意味するのはどこですか?

于 2012-04-24T14:50:26.133 に答える
4

.append()それらの中に連結を入れることによって誤用しています!これは、使用されることになっているものの全体のポイントを逃しStringBuilderます。

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

する必要があります

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

これは、三項演算子を意図したとおりに機能させるための正しいロジックです。

.append()への参照を返すので、必要なだけ呼び出しをStringBuilder連鎖させることができます。.append()

文字列の連結を内部に配置するときはいつでも、メモリ、CPUサイクルを消費し、ガベージコレクションが必要になるため、より多くのリソースを使用する.append()中間オブジェクトを作成するだけです。String

StringBuilderまた、無駄な割り当てやガベージの作成を避けるために、コンテンツの予想よりもわずかに大きいデフォルトサイズで事前に割り当てる必要があります。

コンストラクターについては、 Javadocを参照してください。StringBuilder(int)

于 2012-04-24T14:52:51.827 に答える
3

問題はあなたの「+」から来ています。

  1. StringBuilder を使用する場合は、'+' を使用しないでください: 効率的ではありません
  2. "," + andat==null?"null":andatandat",null"==null?"null":andatが null の場合は次のようになります。

「+」文字列連結は、三項演算子よりも優先されます

String で「+」を使用すると、コンパイラは実際にそれを StringBuilder (または Java5 より前の StringBuffer) に変換します。

だから持っている

String s = a + b + c;

実際には次のように翻訳されます。

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

したがって、StringBuilder 内で + を使用すると、不要な StringBuilder をさらに作成するため、逆効果になります。

于 2012-04-24T14:51:35.213 に答える