ãã®ç¹ã§ãéçã¢ãã©ã€ã¶ãŒã¯ãããªãã®é£ã«åº§ã£ãŠããªããã³ãŒããæžãã®ãèŠãçµéšè±å¯ãªå人ã®ãããªãã®ã§ãã 圌ã¯ããªãã«ãã³ããŒãããšãã«ééããããšèšãã ãã§ãªãããããããããªãã¯ãã®ããã«æžãããšã¯ã§ããŸãããèªåã§ããã¥ã¡ã³ããèŠãŠãã ããããšèšããŸãã ãã®ãããªåå¿ã¯ãããªããæ¬åœã«ããªãã®ä»äºã§ééãããã®ã ããäŒããããªãã決ããŠå¿ èŠãšããªããã®ã«ã€ããŠã¯é»ã£ãŠããã®ã§ãããã¥ã¡ã³ãèªäœããã䟿å©ã§ãã
ãã®æçš¿ã§ã¯ãFindBugséçã¢ãã©ã€ã¶ãŒã®äœ¿çšã«ã€ããŠåŠãã Javaã®è€éãã«ã€ããŠèª¬æããŸãã ãããããããªãã«ãšã£ãŠäºæããªãããšãèµ·ããã§ãããã ãã¹ãŠã®äŸã¯ææ©çã§ã¯ãªããå®éã®ã³ãŒãã«åºã¥ããŠããããšãéèŠã§ãã
äžé æŒç®åïŒïŒ
äžé æŒç®åã»ã©ç°¡åãªãã®ã¯ãªãããã§ãããèœãšãç©ŽããããŸãã ãã¶ã€ã³ã«æ ¹æ¬çãªéãã¯ãªããšæã£ã
Type var = condition ? valTrue : valFalse;
ãã㊠Type var; if(condition) var = valTrue; else var = valFalse;
ç¹çŽ°ããããããšãããããŸããã äžé æŒç®åã¯è€éãªåŒã®äžéšã§ããå¯èœæ§ãããããããã®çµæã¯ã³ã³ãã€ã«æ®µéã§å®çŸ©ãããç¹å®ã®åã§ãªããã°ãªããŸããã ãããã£ãŠãif-formã®çã®æ¡ä»¶äžã§ã¯ãã³ã³ãã€ã©ãŒã¯valTrueãçŽã¡ã«Typeåã«ãã£ã¹ãããäžé æŒç®åã®åœ¢åŒã§ãæåã«äžè¬çãªåvalTrueããã³valFalseãå°ãïŒvalFalseãè©äŸ¡ãããªããšããäºå®ã«ããããããïŒã次ã«çµæãåã«å°ããŸãã¿ã€ãã ããªããã£ãåãšãã®äžã®ã©ãããŒïŒæŽæ°ãããã«ãªã©ïŒãåŒã«å«ãŸããå Žåã匷å¶èŠåã¯å®å šã«èªæã§ã¯ãããŸããããã¹ãŠã®èŠåã¯JLS 15.25ã§è©³çŽ°ã«èª¬æãããŠããŸãã ããã€ãã®äŸãèŠãŠã¿ãŸãããã
Number n = flag ? new Integer(1) : new Double(2.0);
ãã©ã°ãèšå®ãããŠããå Žåãnã§äœãèµ·ãããŸããïŒ å€ã1.0ã®Doubleãªããžã§ã¯ãã ãªããžã§ã¯ããäœæããç§ãã¡ã®äžåšçšãªè©Šã¿ã¯ãã³ã³ãã€ã©ã«ãšã£ãŠã°ãããŠããŸãã 2çªç®ãš3çªç®ã®åŒæ°ã¯ç°ãªãããªããã£ãåã®ã©ãããŒã§ãããããã³ã³ãã€ã©ã¯ããããå±éããããæ£ç¢ºãªåïŒãã®å Žåã¯doubleïŒã«å°ããŸãã ãããŠãå²ãåœãŠã®ããã«äžé æŒç®åãå®è¡ããåŸããã¯ã·ã³ã°ãåã³å®è¡ãããŸãã åºæ¬çã«ãã³ãŒãã¯ãããšåçã§ãã
Number n; if( flag ) n = Double.valueOf((double) ( new Integer(1).intValue() )); else n = Double.valueOf(new Double(2.0).doubleValue());
ã³ã³ãã€ã©ã®èŠ³ç¹ããèŠããšãã³ãŒãã«ã¯åé¡ããªããåé¡ãªãã³ã³ãã€ã«ã§ããŸãã ããããFindBugsã¯èŠåãåºããŸãã
BX_UNBOXED_AND_COERCED_FOR_TERNARY_OPERATORïŒããªããã£ãå€ã¯ããã¯ã¹åãããŠããããTestTernary.mainã®äžé æŒç®åã«å¯ŸããŠåŒ·å¶ãããŸãïŒæåå[]ïŒãã¡ãããFindBugsã¯Integer.valueOfïŒ1ïŒãæ°ããIntegerïŒ1ïŒãããå¹ççã§ãããšèŠåããŠããŸããã誰ãããã§ã«ãããç¥ã£ãŠããŸãã
ã©ãããããããªããã£ãå€ã¯ãæ¡ä»¶ä»ãäžé æŒç®åïŒbïŒE1ïŒe2æŒç®åïŒã®è©äŸ¡ã®äžéšãšããŠãããã¯ã¹åãããã«å¥ã®ããªããã£ãåã«å€æãããŸãã Javaã®ã»ãã³ãã£ã¯ã¹ã§ã¯ãe1ãše2ãã©ãããããæ°å€ã§ããå Žåãå€ã¯ããã¯ã¹åããããå ±éã¿ã€ãã«å€æ/匷å¶ãããŸãïŒããšãã°ãe1ãIntegeråã§ãe2ãFloatåã§ããå Žåãe1ã¯unboxedã«å€æãããæµ®åå°æ°ç¹å€ãããã³ããã¯ã¹åJLSã»ã¯ã·ã§ã³15.25ãåç §ããŠãã ããã
ãŸãã¯ã次ã®ãããªäŸïŒ
Integer n = flag ? 1 : null;
ãã©ã°ãèšå®ãããŠããªãå Žåãäœæè ã¯nã«nullãå ¥ããããšèããŠããŸãã ããŸããããšæããŸããïŒ ã¯ã ããããè€éã«ããŸãããïŒ
Integer n = flag1 ? 1 : flag2 ? 2 : null;
倧ããéãã¯ãªãããã§ãã ãã ããçŸåšãäž¡æ¹ã®ãã©ã°ãã¯ãªã¢ãããŠããå Žåããã®è¡ã¯NullPointerExceptionãã¹ããŒããŸãã å³äžé æŒç®åã®ãªãã·ã§ã³ã¯intããã³nullã§ãããããçµæã®åã¯æŽæ°ã§ãã å·ŠåŽã®ãªãã·ã§ã³ã¯intããã³Integerã§ãããããJavaã«ãŒã«ã«åŸã£ãŠãçµæã¯intã«ãªããŸãã ãããè¡ãã«ã¯ãäŸå€ãã¹ããŒããintValueãåŒã³åºããŠããã¯ã¹å解é€ãå®è¡ããå¿ èŠããããŸãã ã³ãŒãã¯ãããšåçã§ãïŒ
Integer n; if( flag1 ) n = Integer.valueOf(1); else { if( flag2 ) n = Integer.valueOf(Integer.valueOf(2).intValue()); else n = Integer.valueOf(((Integer)null).intValue()); }
FindBugsã¯ããšã©ãŒãçãã®ã«ååãª2ã€ã®ã¡ãã»ãŒãžã衚瀺ããŸãã
BX_UNBOXING_IMMEDIATELY_REBOXEDïŒããã¯ã¹åãããå€ã¯ããã¯ã¹å解é€ãããããã«TestTernary.mainã§åããã¯ã¹åãããŸãïŒæåå[]ïŒ
NP_NULL_ON_SOME_PATHïŒTestTernary.mainã§ã®nullã®nullãã€ã³ã¿ãŒéåç §ã®å¯èœæ§ïŒString []ïŒ
å®è¡ãããå Žåãnullå€ãéæ¥åç §ãããããšãä¿èšŒããã¹ããŒãã¡ã³ãã®åå²ããããã³ãŒãã®å®è¡æã«NullPointerExceptionãçæãããŸãã
ããŠããã®ãããã¯ã®æåŸã®äŸïŒ
double[] vals = new double[] {1.0, 2.0, 3.0}; double getVal(int idx) { return (idx < 0 || idx >= vals.length) ? null : vals[idx]; }
åœç¶ã®ããšãªããããã®ã³ãŒãã¯æ©èœããŸãããããªããã£ãåãè¿ãé¢æ°ã¯ã©ã®ããã«nullãè¿ãããšãã§ããŸããïŒ åé¡ãªãã³ã³ãã€ã«ã§ããã®ã¯é©ãã¹ãããšã§ãã ããŠããªãã³ã³ãã€ã«ããã®ã-ããªãã¯ãã§ã«ç解ããŠããŸãã
æ¥ä»åœ¢åŒ
Javaã§æ¥ä»ãšæå»ããã©ãŒãããããã«ã¯ãDateFormatã€ã³ã¿ãŒãã§ãŒã¹ãå®è£ ããã¯ã©ã¹ã䜿çšããããšããå§ãããŸãã ããšãã°ã次ã®ããã«ãªããŸãã
public String getDate() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); }
å€ãã®å Žåãã¯ã©ã¹ã¯åã圢åŒãåå©çšããŸãã å€ãã®äººãæé©åã®ã¢ã€ãã¢ãæãã€ããŸããå ±éã®ã€ã³ã¹ã¿ã³ã¹ã䜿çšã§ãããã³ã«ãã©ãŒããããªããžã§ã¯ããäœæããã®ã¯ãªãã§ããïŒ
private static final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public String getDate() { return format.format(new Date()); }
ããã¯ãšãŠãçŸãããŠã¯ãŒã«ã§ãããæ®å¿µãªããæ©èœããŸããã ããæ£ç¢ºã«æ©èœããŸãããæã å£ããŸãã å®éãDateFormatã®ããã¥ã¡ã³ãã«ã¯æ¬¡ã®ããã«æžãããŠããŸã ïŒ
æ¥ä»åœ¢åŒã¯åæãããŸããã ã¹ã¬ããããšã«åå¥ã®åœ¢åŒã€ã³ã¹ã¿ã³ã¹ãäœæããããšããå§ãããŸãã è€æ°ã®ã¹ã¬ããããã©ãŒãããã«åæã«ã¢ã¯ã»ã¹ããå Žåãå€éšã§åæããå¿ èŠããããŸãã
SimpleDateFormatã®å éšå®è£ ãèŠãã°ãããã¯äºå®ã§ãã formatïŒïŒã¡ãœãããå®è¡ããéçšã§ããªããžã§ã¯ãã¯ã¯ã©ã¹ã®ãã£ãŒã«ãã«æžã蟌ã¿ãŸãããã®ããã2ã€ã®ã¹ããªãŒã ããSimpleDateFormatãåæã«äœ¿çšãããšãããçšåºŠã®ç¢ºçã§èª€ã£ãçµæã«ãªããŸãã FindBugsãããã«ã€ããŠæžããŠããããšã¯æ¬¡ã®ãšããã§ãã
STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCEïŒTestDate.getDateïŒïŒã®éçjava.text.DateFormatã®ã¡ãœããã®åŒã³åºã
JavaDocãè¿°ã¹ãŠããããã«ãDateFormatsã¯æ¬è³ªçã«ãã«ãã¹ã¬ããã§ã®äœ¿çšã«ã¯å®å šã§ã¯ãããŸããã æ€åºåšã¯ãéçãã£ãŒã«ããä»ããŠååŸãããDateFormatã®ã€ã³ã¹ã¿ã³ã¹ãžã®åŒã³åºããæ€åºããŸããã ããã¯çãããããã§ãã
詳现ã«ã€ããŠã¯ã Sun BugïŒ6231579ããã³Sun BugïŒ6178997ãåç §ããŠãã ãã ã
BigDecimalã®èœãšãç©Ž
BigDecimalã¯ã©ã¹ã䜿çšãããšãä»»æã®ç²ŸåºŠã®å°æ°ãæ ŒçŽã§ããããšãåŠã³ãdoubleã®ã³ã³ã¹ãã©ã¯ã¿ãŒãããããšãèŠãŠããã¹ãŠãæ確ã§ã次ã®ããã«å®è¡ã§ãããšå€æãã人ãããŸãã
System.out.println(new BigDecimal(1.1));
誰ãå®éã«ãããè¡ãããšãçŠæ¢ããŠããŸãããçµæã¯äºæ³å€ã®ããã«æãããããããŸããïŒ1.100000000000000088817841970012523233890533447265625ã ããã¯ãããªããã£ãdoubleãIEEE754圢åŒã§æ ŒçŽãããŠããããã«çºçããŸããIEEE754圢åŒã§ã¯ã1.1ãå®å šã«æ£ç¢ºã«è¡šãããšã¯ã§ããŸããïŒãã€ããªè¡šèšã§ã¯ãç¡éã®åšæåæ°ãååŸãããŸãïŒã ãããã£ãŠã1.1ã«è¿ãæ倧å€ãããã«æ ŒçŽãããŸãã BigDecimalïŒdoubleïŒã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãéã«æ£ç¢ºã«åäœããŸããIEEE754ã®æå®ãããæ°å€ã10é²æ°ã«å€æããã®ãçæ³çã§ãïŒæçµ2é²å°æ°ã¯åžžã«æçµ10é²æ°ãšããŠè¡šçŸå¯èœã§ãïŒã 1.1ãBigDecimalãšããŠæ£ç¢ºã«è¡šç€ºããå Žåã¯ã
new BigDecimal("1.1")
ãŸãã¯
BigDecimal.valueOf(1.1)
ãããããèšè¿°ã§ããŸãã ããã«çªå·ãåºåããã«ãããã«å¯ŸããŠäœããã®æäœãè¡ããšããšã©ãŒã®åå ãããããªãå ŽåããããŸãã FindBugsã¯èŠåDMI_BIGDECIMAL_CONSTRUCTED_FROM_DOUBLEãçºè¡ããåãã¢ããã€ã¹ãæäŸããŸãã
ãããŠãããäžã€ãããŸãïŒ
BigDecimal d1 = new BigDecimal("1.1"); BigDecimal d2 = new BigDecimal("1.10"); System.out.println(d1.equals(d2));
å®éãd1ãšd2ã¯åãæ°å€ã§ãããequalsã¯falseãè¿ããŸããããã¯ãæ°å€ã®å€ã ãã§ãªããçŸåšã®é åºïŒå°æ°ç¹ä»¥äžã®æ¡æ°ïŒãæ¯èŒããããã§ãã ããã¯ããã¥ã¡ã³ãã«æžãããŠããŸãããequalsã®ãããªããªãã¿ã®ã¡ãœããã®ããã¥ã¡ã³ããèªã人ã¯ã»ãšãã©ããŸããã ãã®ãããªåé¡ã¯ããã«ã¯çºçããŸããã æ®å¿µãªãããFindBugsèªäœã¯ããã«ã€ããŠèŠåããŠããŸããããäžè¬çãªæ¡åŒµæ©èœã§ããfb-contribããã ããã®ãã°ãèæ ®ãããŠããŸãã
MDM_BIGDECIMAL_EQUALS
equalsïŒïŒã¯ã2ã€ã®java.math.BigDecimalæ°å€ãæ¯èŒããããã«åŒã³åºãããŸãã 2ã€ã®BigDecimalãªããžã§ã¯ãã¯ãå€ãšã¹ã±ãŒã«ã®äž¡æ¹ãçããå Žåã«ã®ã¿çããããã2.0ã¯2.00ãšçãããªããããããã¯éåžžééãã§ãã BigDecimalãªããžã§ã¯ãã®æ°åŠçç䟡æ§ãæ¯èŒããã«ã¯ã代ããã«compareToïŒïŒã䜿çšããŸãã
æ¹è¡ãšprintf
å€ãã®å ŽåãCã®åŸã«Javaã«åãæ¿ããããã°ã©ããŒã¯ã PrintStream.printf ïŒããã³PrintWriter.printfãªã©ïŒãåãã§çºèŠããŸãã ããšãã°ãCã®å Žåãšåæ§ã«ãæ°ããããšãåŠã¶å¿ èŠã¯ãããŸããã å®éã«ã¯éãããããŸãã ãã®ãã¡ã®1ã€ã¯æ¹è¡ã§ãã
Cèšèªã§ã¯ãããã¹ãã¹ããªãŒã ãšãã€ããªã¹ããªãŒã ã«åãããŠããŸãã ããã¹ãã¹ããªãŒã ãžã®æå '\ n'ã®åºåã¯ãã·ã¹ãã äŸåã®ã©ã€ã³ãã£ãŒãïŒWindowsã§ã¯ "\ r \ n"ïŒã«èªåçã«å€æãããŸãã Javaã«ã¯ãã®ãããªåé¢ã¯ãããŸãããæ£ããæåã·ãŒã±ã³ã¹ãåºåã¹ããªãŒã ã«æž¡ãå¿ èŠããããŸãã ããã¯ãããšãã°PrintStream.printlnãã¡ããªãŒã®ã¡ãœããã«ãã£ãŠèªåçã«è¡ãããŸãã ãã ããprintfã䜿çšããå ŽåãæžåŒæååã«ã\ nããæž¡ãããšã¯ã\ nãã ãã§ãããã·ã¹ãã äŸåã®æ¹è¡ã§ã¯ãããŸããã ããšãã°ã次ã®ã³ãŒããèšè¿°ããŸãã
System.out.printf("%s\n", "str#1"); System.out.println("str#2");
çµæããã¡ã€ã«ã«ãªãã€ã¬ã¯ããããšã次ã®ããã«è¡šç€ºãããŸãã
ãããã£ãŠã1ã€ã®ã¹ã¬ããã§ã©ã€ã³ãã£ãŒãã®å¥åŠãªçµã¿åãããååŸã§ããŸãã ç¹ã«äž»ã«Unixã·ã¹ãã ã§äœæ¥ããŠããå Žåããšã©ãŒã«é·æéæ°ä»ããªãããšããããŸãã printfã䜿çšããŠæ£ããæ¹è¡ãæ¿å ¥ããããã«ãç¹æ®ãªãã©ãŒãããæåãïŒ nãã䜿çšãããŸãã FindBugsãããã«ã€ããŠæžããŠããããšã¯æ¬¡ã®ãšããã§ãã
VA_FORMAT_STRING_USES_NEWLINEïŒåœ¢åŒæååã¯TestNewline.mainã§\ nã§ã¯ãªãïŒ nã䜿çšããå¿ èŠããããŸãïŒæåå[]ïŒ
ãã®ãã©ãŒãããæååã«ã¯ãæ¹è¡æåïŒ\ nïŒãå«ãŸããŸãã ãã©ãŒãããæååã§ã¯ãäžè¬çã«ãã©ãããã©ãŒã åºæã®è¡åºåãæåãçæããïŒ nã䜿çšããæ¹ãé©åã§ãã
ããããäžéšã®èªè ã«ãšã£ãŠã¯ãäžèšã®ãã¹ãŠãé·ãéç¥ãããŠããŸãã ãããã䜿çšããŠããããã°ã©ãã³ã°èšèªã®æ°ããæ©èœãéããéçã¢ãã©ã€ã¶ãŒããã®èå³æ·±ãèŠåãããããšã¯ééããããŸããã