åæã¯ãã¡ãã
http://openjdk.java.net/projects/amber/LVTIstyle.html
泚æïŒ2018/03/25ïŒJSTïŒæç¹ã®å 容ã§ãã
ãã®æ©èœã«ã¯æ§ã ãªè«äºããããäžæ¹ã§ã¯ãã®æ©èœãå¯èœã«ããç°¡æœæ§ãæè¿ãã声ãããã®ã«å¯Ÿããä»æ¹ã§ã¯ãã³ãŒããèªã人ã«ãšã£ãŠéèŠãªåæ å ±ã奪ãããèªã¿ããããæãªãããæããããããšãã声ããããŸãããããã®ã°ã«ãŒãã®å£°ãééã£ãŠã¯ããŸãããåé·ãªæ å ±ãæé€ããŠã³ãŒããããèªã¿ãããããããšãã§ããã°ãæçãªæ å ±ãéãããšã§ã³ãŒããèªã¿ã«ããããããšãã§ããŸããä»ã«ã¯ãÂ
ããŒã«ã«å€æ°å®£èšã¯åç¬ã§ã¯ååšããŸããã åšå²ã®ã³ãŒãã«ãã£ãŠãÂ
ç¹ã«ããã§ã¯ãããã°ã©ã ã®å ¥åãç·šéã«å¿ èŠãªããŒããŒããå©ãéã«ã¯é¢å¿ããããŸãããç°¡æœãã¯ã³ãŒãèšè¿°è ã«ãšã£ãŠã¯çŽ æŽãããããŒãã¹ã«ãªããããããŸããããããã«æ³šåãããšãçµæãšããŠåŸãããããã°ã©ã ã®ãããããããåäžããããšãããäž»èŠãªç®çã倱ã£ãŠããŸããŸãã
2ã€ã®çç±ããããŸãã1åç®ã®çç±ã¯ãã³ãŒãã¯IDEã®å€ã§èªã¿èŸŒãŸããããšãå€ããšããããšã§ããã³ãŒãã¯ãIDEæ©èœãå©çšã§ããªãå€ãã®å ŽæãäŸãã°ããã¥ã¡ã³ãå ã®ã¹ãããããã€ã³ã¿ãŒãããäžã®ãªããžããªã®åç §ããŸãã¯ããããã¡ã€ã«ã«çŸããŸããã³ãŒããäœãããã®ããç解ããããã ãã«ãã³ãŒããIDEã«ã€ã³ããŒãããå¿ èŠãããã®ã¯éçç£çã§ãã
ããäžã€ã®çç±ã¯ãIDEå ã§ã³ãŒããèªã¿èŸŒãã§ãããšãã§ããå€æ°ã«é¢ãã詳现æ å ±ãIDEã«åãåãããããã«æ瀺çãªã¢ã¯ã·ã§ã³ãå¿ èŠãªå Žåãå€ããšããããšã§ããäŸãã°ãÂ
ã³ãŒãã¯èªæã§ãªããã°ãªããŸãããããŒã«ã®å©ããå¿ èŠãšããã«ããã®æ£é¢ããç解ã§ããå¿ èŠããããŸãã
æ瀺çãªåãçç¥ãããšããã€ãºãæžå°ã§ããŸãããããã¯çç¥ããŠããããããããæãªãããªãå Žåã«éããŸããåã¯ã³ãŒããªãŒããŒã«æ å ±ãäŒããå¯äžã®æ¹æ³ã§ã¯ãããŸããã ä»ã®æ段ã«ã¯ãå€æ°ã®ååãšã€ãã·ã£ã©ã€ã¶åŒããããŸãããããã®ãã£ã³ãã«ã®1ã€ããã¥ãŒãããŠãåé¡ãªããã©ãããå€æããã«ã¯ã䜿çšå¯èœãªãã¹ãŠã®ãã£ã³ãã«ãèæ ®ããå¿ èŠããããŸãã
å€æ°ã®åããã®ååã«èšå·åããŠãè«ççãªçµè«ã«éãããšããã³ã¬ãªã¢ã³èšæ³ïŒHungarian NotationïŒã«ãªããŸãã æ瀺çãªåãšåæ§ã«ãããã¯æãšããŠåœ¹ã«ç«ã€ããšãããã°ãæ··ä¹±ããããšããããŸãã ãã®äŸã§ã¯ãÂ
次ã®äŸã§ã¯ãaddã¡ãœãããç¹å¥ãªé ç®ãæåŸã®ãªã¹ãèŠçŽ ãšããŠæ瀺çã«è¿œå ããã®ã§ãæåŸ éãæåŸã«åŠçãããŸãã
ããã§ããã®ã³ãŒããÂ
Â
ããã¯Â
G3. Consider
ããŒã«ã«å€æ°ã¯ã³ã³ã¹ãã©ã¯ã¿ã§åæåãããããšãå€ããã³ã³ã¹ãã©ã¯ããããã¯ã©ã¹ã®ååã¯å·ŠåŽã§æ瀺çãªåãšããŠé »ç¹ã«ç¹°ãè¿ãããŸããåã®ååãé·ãå ŽåãÂ
G4. Use
æååã®ã³ã¬ã¯ã·ã§ã³ãåããæãããçºçããæååãçºèŠãããšããã³ãŒããèããŠã¿ãŸãããã以äžã®ãããªæãã§ãã
äž»ãªåé¡ã¯ãå€æ°ã䜿çšããã³ãŒããå ·äœçãªå®è£ ã«äŸåããå¯èœæ§ãããããšã§ããå€æ°ã®ã€ãã·ã£ã©ã€ã¶ãå°æ¥å€æŽãããå Žåãæšæž¬ãããåãå€æŽãããçµæãšããŠãã®å€æ°ã䜿çšããåŸç¶ã®ã³ãŒãã§ãšã©ãŒããã°ãçºçããå¯èœæ§ããããŸãã
ã¬ã€ãã©ã€ã³G2ã§æšå¥šãããŠããããã«ãããŒã«ã«å€æ°ã®ã¹ã³ãŒããå°ããå ŽåãåŸç¶ã³ãŒãã«åœ±é¿ãäžããå¯èœæ§ãããå ·äœçãªå®è£ ã®ãæŒããã«ãããªã¹ã¯ã¯éå®çã§ããå€æ°ãæ°è¡é¢ããã³ãŒãã§ã®ã¿äœ¿çšãããŠããå Žåã¯ãåé¡ãåé¿ããããåé¡çºçæã«åé¡ãç·©åãããããã®ã¯ç°¡åã§ãã
ãã®ç¹å®ã®ã±ãŒã¹ã§ã¯ãÂ
G6. Take care when using
Â
以äžã®äŸãèããŠã¿ãŸãããã
ãžã§ããªãã¯ã¡ãœããã¯åæšè«ãæ¡çšããŠããã®ã§ãããã°ã©ããæ瀺çãªååŒæ°ãæäŸããããšã¯ã»ãšãã©ãããŸãããååãªåæ å ±ãæäŸããå®éã®ã¡ãœããåŒæ°ããªãå Žåããžã§ããªãã¯ã¡ãœããã®æšè«ã¯ã¿ãŒã²ããã®åã«äŸåããŸããÂ
G7. Take care when using
ããªããã£ããªãªãã©ã«ã¯ãÂ
booleanãcharacterãÂ
次ã®ã³ãŒãã¯ãå€ããšãÂ
http://openjdk.java.net/projects/amber/LVTIstyle.html
泚æïŒ2018/03/25ïŒJSTïŒæç¹ã®å 容ã§ãã
Introduction
Java SE 10ã§ã¯ãããŒã«ã«å€æ°ã®åæšè«ãå°å ¥ãããŸããã以åã¯ããã¹ãŠã®ããŒã«ã«å€æ°å®£èšã§ã¯ãå·ŠåŽã«æ瀺çãªïŒãããã§ã¹ãïŒåãå¿ èŠã§ãããåæšè«ã§ã¯ãæ瀺çãªåããã€ãã·ã£ã©ã€ã¶ïŒåæååïŒãæã€ããŒã«ã«å€æ°å®£èšã®äºçŽåã®ååÂvar
 ã«çœ®ãæããããšãã§ããŸããå€æ°ã®åã¯ãã€ãã·ã£ã©ã€ã¶ã®åããæšæž¬ãããŸãããã®æ©èœã«ã¯æ§ã ãªè«äºããããäžæ¹ã§ã¯ãã®æ©èœãå¯èœã«ããç°¡æœæ§ãæè¿ãã声ãããã®ã«å¯Ÿããä»æ¹ã§ã¯ãã³ãŒããèªã人ã«ãšã£ãŠéèŠãªåæ å ±ã奪ãããèªã¿ããããæãªãããæããããããšãã声ããããŸãããããã®ã°ã«ãŒãã®å£°ãééã£ãŠã¯ããŸãããåé·ãªæ å ±ãæé€ããŠã³ãŒããããèªã¿ãããããããšãã§ããã°ãæçãªæ å ±ãéãããšã§ã³ãŒããèªã¿ã«ããããããšãã§ããŸããä»ã«ã¯ãÂ
var
 ãé床ã«äœ¿çšããçµæãããæªãJavaã³ãŒããæžãããããšãæžå¿µããã°ã«ãŒããããŸãããããæ£ããææã§ã¯ãããŸãããããè¯ãJavaã³ãŒããæžãããå¯èœæ§ããããŸãããã¹ãŠã®æ©èœãšåæ§ã«ãå€æããŠäœ¿çšããå¿
èŠããããŸãããã€å©çšãã¹ããã¹ãããã®äžè¬èŠåã¯ãããŸãããããŒã«ã«å€æ°å®£èšã¯åç¬ã§ã¯ååšããŸããã åšå²ã®ã³ãŒãã«ãã£ãŠãÂ
var
 ã䜿çšããå Žåã®åœ±é¿ã«åœ±é¿ãåãã ããå§åããããããå¯èœæ§ããããŸãã ãã®ããã¥ã¡ã³ãã®ç®çã¯ãåšå²ã®ã³ãŒãã var
 宣èšã«äžãã圱é¿ã調ã¹ããã¬ãŒããªãã説æãã var
 ãå¹æçã«äœ¿çšããããã®ã¬ã€ãã©ã€ã³ãæäŸããããšã§ããPrinciples
P1. Reading code is more important than writing code.
ã³ãŒãã¯æžãããããèªãŸããããšã®ã»ãããã£ãšå€ããããã«ãã³ãŒããæžããšããç§ãã¡ã¯éåžžãé ã®äžã«ã¯å šäœã®ã³ã³ããã¹ãããããæéãæããŸãããã³ãŒããèªãã§ãããšãã«ã¯ãã³ã³ããã¹ãã»ã¹ã€ãããé »ç¹ã«è¡ããããã£ãšæ¥ãã§ããå¯èœæ§ããããŸããç¹å®ã®èšèªæ©èœã䜿çšãããŠãããã©ããã¯ãå ã®ã³ãŒãèšè¿°è ã§ã¯ãªããããã°ã©ã èªè ã«äžãã圱é¿ã«ãã£ãŠæ±ºå®ãããã¹ãã§ããããã°ã©ã ãçããã°çãã»ããæãŸãããããããŸããããçããããšããã°ã©ã ãç解ããã®ã«åœ¹ç«ã€æ å ±ãçç¥ãããå¯èœæ§ããããŸããããã§ã®äžå¿çãªåé¡ã¯ããããããããæ倧åããããã«ããã°ã©ã ã®é©åãªãµã€ãºãèŠã€ããããšã§ããç¹ã«ããã§ã¯ãããã°ã©ã ã®å ¥åãç·šéã«å¿ èŠãªããŒããŒããå©ãéã«ã¯é¢å¿ããããŸãããç°¡æœãã¯ã³ãŒãèšè¿°è ã«ãšã£ãŠã¯çŽ æŽãããããŒãã¹ã«ãªããããããŸããããããã«æ³šåãããšãçµæãšããŠåŸãããããã°ã©ã ã®ãããããããåäžããããšãããäž»èŠãªç®çã倱ã£ãŠããŸããŸãã
P2. Code should be clear from local reasoning.
ã³ãŒãã®èªè ã¯ã宣èšãããå€æ°ã®å©çšãšãšãã«Âvar
 ã®å®£èšãèŠãŠãäœãèµ·ããŠããã®ããããã«ç解ã§ããã¯ãã§ããçæ³çã«ã¯ãã¹ãããããŸãã¯ãããã®ã³ã³ããã¹ãã®ã¿ã䜿çšããŠãã³ãŒãã容æã«ç解ã§ããããã«ããå¿
èŠããããŸãã var
 宣èšãç解ããããã«ã³ãŒãã®åšãã®ããã€ãã®å ŽæãèŠãå¿
èŠãããå Žåã¯ã var
 ã䜿ãã«ã¯è¯ãç¶æ³ã§ã¯ãªããããããŸããããããŠå床ç³ãäžããŸãããã³ãŒãèªäœã«åé¡ãããå¯èœæ§ããããŸããP3. Code readability shouldn't depend on IDEs.
IDEã§ã³ãŒããèªã¿æžãããããšãå€ããããIDEã®ã³ãŒã解ææ©èœã«å€§ããäŸåããããªããŸããå宣èšã¯ãåã決ããå€æ°ãåžžã«æã瀺ãããšãã§ããã®ã§ãã©ãã§ãÂvar
 ã䜿ãã ãã§ããã®ã§ã¯ãªãã§ããããã2ã€ã®çç±ããããŸãã1åç®ã®çç±ã¯ãã³ãŒãã¯IDEã®å€ã§èªã¿èŸŒãŸããããšãå€ããšããããšã§ããã³ãŒãã¯ãIDEæ©èœãå©çšã§ããªãå€ãã®å ŽæãäŸãã°ããã¥ã¡ã³ãå ã®ã¹ãããããã€ã³ã¿ãŒãããäžã®ãªããžããªã®åç §ããŸãã¯ããããã¡ã€ã«ã«çŸããŸããã³ãŒããäœãããã®ããç解ããããã ãã«ãã³ãŒããIDEã«ã€ã³ããŒãããå¿ èŠãããã®ã¯éçç£çã§ãã
ããäžã€ã®çç±ã¯ãIDEå ã§ã³ãŒããèªã¿èŸŒãã§ãããšãã§ããå€æ°ã«é¢ãã詳现æ å ±ãIDEã«åãåãããããã«æ瀺çãªã¢ã¯ã·ã§ã³ãå¿ èŠãªå Žåãå€ããšããããšã§ããäŸãã°ãÂ
var
 ã䜿ã£ãŠå®£èšãããå€æ°ã®åãåãåãããããã«ãå€æ°äžã«ãã€ã³ã¿ã眮ããŠãããã¢ãããåŸ
ããªããã°ãªããªããããããŸãããããã¯ã»ãã®äžç¬ããæéãããããªããããããŸããããã³ãŒããªãŒãã£ã³ã°ã®æµãã劚害ããŸããã³ãŒãã¯èªæã§ãªããã°ãªããŸãããããŒã«ã®å©ããå¿ èŠãšããã«ããã®æ£é¢ããç解ã§ããå¿ èŠããããŸãã
P4. Explicit types are a tradeoff.
æŽå²çã«ãJavaã§ã¯ãåãæ瀺çã«å«ããããã«ããŒã«ã«å€æ°ã®å®£èšãå¿ èŠã§ãããæ瀺çãªåã¯éåžžã«åœ¹ç«ã€ããšããããŸãããæã«ã¯ããã»ã©éèŠã§ã¯ãªãããšããããæã«ã¯éªéã«ãªãããšããããŸããæ瀺çãªåãå¿ èŠãšãããšãæçšãªæ å ±ã«æŒãå¯ãããã€ãºãå¢ããå¯èœæ§ããããŸããæ瀺çãªåãçç¥ãããšããã€ãºãæžå°ã§ããŸãããããã¯çç¥ããŠããããããããæãªãããªãå Žåã«éããŸããåã¯ã³ãŒããªãŒããŒã«æ å ±ãäŒããå¯äžã®æ¹æ³ã§ã¯ãããŸããã ä»ã®æ段ã«ã¯ãå€æ°ã®ååãšã€ãã·ã£ã©ã€ã¶åŒããããŸãããããã®ãã£ã³ãã«ã®1ã€ããã¥ãŒãããŠãåé¡ãªããã©ãããå€æããã«ã¯ã䜿çšå¯èœãªãã¹ãŠã®ãã£ã³ãã«ãèæ ®ããå¿ èŠããããŸãã
Guidelines
G1. Choose variable names that provide useful information.
ããã¯äžè¬çã«ã¯è¯ãæ¹æ³ã§ãããÂvar
 ã®æèã§ã¯ãã£ãšéèŠã§ãã  var
 宣èšã§ã¯ãå€æ°ã®æå³ãšäœ¿çšã«é¢ããæ
å ±ãå€æ°ã®ååã䜿ã£ãŠäŒããããšãã§ããŸããæ瀺çãªåã var
 ã«çœ®ãæããã«ã¯ãå€æ°åãæ¹åããå¿
èŠããããŸãã äŸãã°ä»¥äžã®ãããªå
·åã§ãããã®äŸã§ã¯ã圹ã«ç«ããªãå€æ°åããå€æ°ã®åãã€ã¡ãŒãžã§ããååã«çœ®ãæããŸãããå€æ°åã¯ãvar宣èšã§æé»çã«èšè¿°ãããŠããŸãã// ORIGINAL
List<Customer> x = dbconn.executeQuery(query);
// GOOD
var custList = dbconn.executeQuery(query);
å€æ°ã®åããã®ååã«èšå·åããŠãè«ççãªçµè«ã«éãããšããã³ã¬ãªã¢ã³èšæ³ïŒHungarian NotationïŒã«ãªããŸãã æ瀺çãªåãšåæ§ã«ãããã¯æãšããŠåœ¹ã«ç«ã€ããšãããã°ãæ··ä¹±ããããšããããŸãã ãã®äŸã§ã¯ãÂ
custList
 ãšããååã¯ã List
 ãè¿ãããšãæ瀺ããŠããŸãããéèŠã§ã¯ãªããããããŸããã å³å¯ãªåã®ä»£ããã«ãå€æ°åãã顧客ïŒcustomersïŒãã®ããå€æ°ã®åœ¹ç®ãæ§è³ªãè¡šçŸããã»ããè¯ãå ŽåããããŸãã// ORIGINAL
try (Stream<Customer> result = dbconn.executeQuery(query)) {
return result.map(...)
.filter(...)
.findAny();
}
// GOOD
try (var customers = dbconn.executeQuery(query)) {
return customers.map(...)
.filter(...)
.findAny();
}
G2. Minimize the scope of local variables.
ããŒã«ã«å€æ°ã®ã¹ã³ãŒããå¶éããããšã¯äžè¬çã«ã¯è¯ãæ¹æ³ã§ãããã®æ¹æ³ã¯ãEffective JavaïŒç¬¬3çïŒã®Item 57ã«èšè¿°ãããŠããŸããÂvar
 ã䜿ãå Žåã¯äœåãªåãå ããŠé©çšããŸãã次ã®äŸã§ã¯ãaddã¡ãœãããç¹å¥ãªé ç®ãæåŸã®ãªã¹ãèŠçŽ ãšããŠæ瀺çã«è¿œå ããã®ã§ãæåŸ éãæåŸã«åŠçãããŸãã
ä»åºŠã¯ãéè€ããé ç®ãåé€ããããã«ãããã°ã©ããŒããã®ã³ãŒããä¿®æ£ããŠãvar items = new ArrayList<Item>(...);
items.add(MUST_BE_PROCESSED_LAST);
for (var item : items) ...
ArrayList
ã®ä»£ããã« HashSet
ã䜿çšããããšã«ããŸãããã®ã³ãŒãã«ã¯ãã°ããããŸããSetã«ã¯å®çŸ©æžã¿ã®å埩é åºããªãããã§ãã ããããããã°ã©ããŒã¯Âvar items = new HashSet<Item>(...);
items.add(MUST_BE_PROCESSED_LAST);
for (var item : items) ...
items
 å€æ°ã®äœ¿çšã宣èšã«é£æ¥ããŠããã®ã§ãããã«ãã®ãã°ãä¿®æ£ããå¯èœæ§ããããŸããããã§ããã®ã³ãŒããÂ
items
 å€æ°ã®å€§ããªã¹ã³ãŒããæã€å€§ããªã¡ãœããã®äžéšã§ãããšããŸããArrayListããHashSetãžã®å€æŽã®åœ±é¿ã¯ãÂvar items = new HashSet<Item>(...);
// ... 100 lines of code ...
items.add(MUST_BE_PROCESSED_LAST);
for (var item : items) ...
items
 ã宣èšããé ãé¢ããŠäœ¿çšãããããããã¯ããããã¥ãããªã£ãŠããããããã®ãã°ããã£ãšé·ãçãæ®ãå¯èœæ§ããããŸããÂ
items
 ã  List<String>
 ãšããŠæ瀺çã«å®£èšãããŠããå Žåã¯ãã€ãã·ã£ã©ã€ã¶ãå€æŽããã°ãåã Set<String>
 ã«å€æŽããå¿
èŠããããŸããããã«ãããããã°ã©ãã¯ãã¡ãœããã®æ®ãã®éšåã調ã¹ãŠããã®ãããªå€æŽã®åœ±é¿ãåããã³ãŒãã調ã¹ãããšãã§ããŸãïŒãããŠå床ããããªããªãå ŽåããããŸãïŒã  var
 ã䜿ããšãã®æåããªããªãããããã®ãããªã³ãŒãã§ãã°ãå°å
¥ãããå±éºæ§ãå¢ãå¯èœæ§ããããŸããããã¯Â
var
 ã䜿çšããŠããããšã«å¯Ÿããè°è«ã®ããã«æãããããããŸããããå®éã¯ããã§ã¯ãããŸããã var
 ã䜿çšããæåã®äŸã¯å
šãåé¡ãããŸããããã®åé¡ã¯ãå€æ°ã®ã¹ã³ãŒãã倧ããå Žåã«ã®ã¿çºçããŸãããã®ãããªå Žåã«åã«Â var
 ãé¿ããã®ã§ã¯ãªããããŒã«ã«å€æ°ã®ã¹ã³ãŒããçããããã«ã³ãŒããå€æŽãã¹ãã§ããã®åŸã«Â var
 ã§å®£èšããã ãã§ããG3. Consider var
when the initializer provides sufficient information to the reader.
ããŒã«ã«å€æ°ã¯ã³ã³ã¹ãã©ã¯ã¿ã§åæåãããããšãå€ããã³ã³ã¹ãã©ã¯ããããã¯ã©ã¹ã®ååã¯å·ŠåŽã§æ瀺çãªåãšããŠé »ç¹ã«ç¹°ãè¿ãããŸããåã®ååãé·ãå Žåã var
 ã䜿çšããŠæ
å ±ã倱ããã«ç°¡æœã«ããããšãã§ããŸãããŸããã€ãã·ã£ã©ã€ã¶ãã³ã³ã¹ãã©ã¯ã¿ã§ã¯ãªãéçãªãã¡ã¯ããªã¡ãœãããªã©ã®ã¡ãœããåŒã³åºãã§ããå ŽåããããŠãã®ååã«ååã«åæ å ±ãå«ãŸããå Žåã«ããåççãªÂ// ORIGINAL
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// GOOD
var outputStream = new ByteArrayOutputStream();
var
 ã®å©çšãšèšããã§ãããããããã®ã±ãŒã¹ã§ã¯ãã¡ãœããåãç¹å®ã®æ»ãå€ã®åã匷ã瀺åããŠãããããå€æ°ã®åæšè«ã«å©çšãããŸãã// ORIGINAL
BufferedReader reader = Files.newBufferedReader(...);
List<String> stringList = List.of("a", "b", "c");
// GOOD
var reader = Files.newBufferedReader(...);
var stringList = List.of("a", "b", "c");
G4. Use var
to break up chained or nested expressions with local variables.
æååã®ã³ã¬ã¯ã·ã§ã³ãåããæãããçºçããæååãçºèŠãããšããã³ãŒããèããŠã¿ãŸãããã以äžã®ãããªæãã§ãããã®ã³ãŒãã¯æ£ããã§ãããåäžã®ã¹ããªãŒã ãã€ãã©ã€ã³ã®ããã«èŠãããããæ··ä¹±ãæãå¯èœæ§ããããŸããå®éãããã¯çãã¹ããªãŒã ã§ããã第1ã®ã¹ããªãŒã ã®çµæã«å¯Ÿãã第2ã®ã¹ããªãŒã ãç¶ããŠç¬¬2ã®ã¹ããªãŒã ã®Âreturn strings.stream()
.collect(groupingBy(s -> s, counting()))
.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey);
Optional
 ã®çµæã®ãããã³ã°ãç¶ããŸããæãèªã¿ããããã®ã³ãŒãã®è¡šçŸã¯ã2ã3è¡ã®ã¹ããŒãã¡ã³ãã§ããããæåã«ã°ã«ãŒããšã³ããªããããã«ãããç¶ããŠãã®Mapãçž®å°ããåŸã«ãïŒååšããå Žåã¯ïŒçµæããããŒãåãåºããŸãã以äžã®ãããªæãã§ããããããäžéå€æ°ã®åãæžãããšã¯ããŸãã«ãè² æ ã«æããã®ã§ãã³ãŒãèšè¿°è ã¯ããããããšããããŠããã®ãããã«ã³ã³ãããŒã«ã»ãããŒãæªããã®ã§ããÂMap<String, Long> freqMap = strings.stream()
.collect(groupingBy(s -> s, counting()));
Optional<Map.Entry<String, Long>> maxEntryOpt = freqMap.entrySet()
.stream()
.max(Map.Entry.comparingByValue());
return maxEntryOpt.map(Map.Entry::getKey);
var
 ã䜿ããšãé«ã³ã¹ããªäžéå€æ°ã®åã®æ瀺çãªå®£èšãããã«ãããèªç¶ã«ã³ãŒããè¡šçŸã§ããŸããæåã®ã¹ããããã¯ãã¡ãœããåŒåºãã®1ã€ã®é·ããã§ãŒã³ã§æ£åœã§å¥œãŸãããããããŸããããé·ãã¡ãœãããã§ãŒã³ãåå²ããæ¹ãããå ŽåããããŸãããããã®ã±ãŒã¹ã§ã®Âvar freqMap = strings.stream()
.collect(groupingBy(s -> s, counting()));
var maxEntryOpt = freqMap.entrySet()
.stream()
.max(Map.Entry.comparingByValue());
return maxEntryOpt.map(Map.Entry::getKey);
var
 ã®äœ¿çšã¯å®è¡å¯èœãªã¢ãããŒãã§ããã2çªç®ã®ã¹ããããã§äžéå€æ°ã®å®å
šãªå®£èšã䜿çšãããšãããã¯åçæ§ã®æ¬ ããéžæè¢ã«ãªããŸãã ä»ã®å€ãã®ç¶æ³ãšåæ§ã«ã var
 ãæ£ãã䜿çšããã«ã¯ãäœããåãé€ãïŒæ瀺çãªåïŒãšäœããè¿œå ããïŒããè¯ãå€æ°åãã³ãŒãã®ããè¯ãæ§é åïŒã®äž¡æ¹ãå¿
èŠãããããŸãããG5. Don't worry too much about "programming to the interface" with local variables.
Javaããã°ã©ãã³ã°ã®äžè¬çãªã€ãã£ãªã ã¯ãå ·è±¡åã®ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ãããããã€ã³ã¿ãã§ãŒã¹åã®å€æ°ã«å²ãåœãŠãããšã§ããããã¯ãã³ãŒããå®è£ ïŒimplementationïŒã®ä»£ããã«æœè±¡ïŒabstractionïŒã«çµã³ã€ãããããå°æ¥ã³ãŒããä¿å®ããéã®æè»æ§ãä¿æãããŸããããããÂ// ORIGINAL
List<String> list = new ArrayList<>();
var
 ã䜿ããšãã€ã³ã¿ãŒãã§ãŒã¹ã§ã¯ãªãå
·è±¡åãæšè«ããŸããããã§ãÂ// Inferred type of list is ArrayList<String>.
var list = new ArrayList<String>();
var
 ã¯ããŒã«ã«å€æ°ã«å¯ŸããŠã®ã¿äœ¿çšã§ããããšãåèããå¿
èŠããããŸãã var
 ã¯ãã£ãŒã«ãåãã¡ãœãããã©ã¡ãŒã¿åãããã³ã¡ãœããæ»ãå€ã®åãæšæž¬ããããã«äœ¿çšã§ããŸããããã€ã³ã¿ãŒãã§ã€ã¹ãžã®ããã°ã©ãã³ã°ãã®ååã¯ããããŸã§ã®ã³ã³ããã¹ããšåããããéèŠã§ããäž»ãªåé¡ã¯ãå€æ°ã䜿çšããã³ãŒããå ·äœçãªå®è£ ã«äŸåããå¯èœæ§ãããããšã§ããå€æ°ã®ã€ãã·ã£ã©ã€ã¶ãå°æ¥å€æŽãããå Žåãæšæž¬ãããåãå€æŽãããçµæãšããŠãã®å€æ°ã䜿çšããåŸç¶ã®ã³ãŒãã§ãšã©ãŒããã°ãçºçããå¯èœæ§ããããŸãã
ã¬ã€ãã©ã€ã³G2ã§æšå¥šãããŠããããã«ãããŒã«ã«å€æ°ã®ã¹ã³ãŒããå°ããå ŽåãåŸç¶ã³ãŒãã«åœ±é¿ãäžããå¯èœæ§ãããå ·äœçãªå®è£ ã®ãæŒããã«ãããªã¹ã¯ã¯éå®çã§ããå€æ°ãæ°è¡é¢ããã³ãŒãã§ã®ã¿äœ¿çšãããŠããå Žåã¯ãåé¡ãåé¿ããããåé¡çºçæã«åé¡ãç·©åãããããã®ã¯ç°¡åã§ãã
ãã®ç¹å®ã®ã±ãŒã¹ã§ã¯ãÂ
List
 ã«ã¯ãªã2ã€ã®ã¡ãœãããã€ãŸã ensureCapacity
 ãšÂ trimToSize
 ã ArrayList
 ã«ã®ã¿å«ãŸããŠããŸãããããã®ã¡ãœããã¯ãªã¹ãã®å
容ã«ã¯åœ±é¿ããŸããããããã£ãŠããããã®ã¡ãœããã®åŒã³åºãã¯ããã°ã©ã ã®æ£ç¢ºãã«åœ±é¿ããŸãããããã¯ãã€ã³ã¿ãã§ãŒã¹ã§ã¯ãªããå
·äœçãªå®è£
ã§ããæšè«åã®åœ±é¿ãããã«æžãããŸããG6. Take care when using var
with diamond or generic methods.
 var
 ãšãã€ã¢ã¢ã³ãæŒç®åã®äž¡æ¹ã®æ©èœã䜿çšãããšãæ¢ã«ååšããæ
å ±ãã掟çå¯èœãªå Žåã«ãæ瀺çãªåæ
å ±ãçç¥ã§ããŸããã§ã¯ãåã宣èšã§äž¡æ¹ãšã䜿çšã§ããã®ã§ããããïŒä»¥äžã®äŸãèããŠã¿ãŸãããã
ããããã€ã¢ã¢ã³ãæŒç®åãÂPriorityQueue<Item> itemQueue = new PriorityQueue<Item>();
var
 ã䜿ã£ãŠåæ
å ±ã倱ããã«æžãçŽãããšãã§ããŸããÂ// OK: both declare variables of type PriorityQueue<Item>
PriorityQueue<Item> itemQueue = new PriorityQueue<>();
var itemQueue = new PriorityQueue<Item>();
var
 ãšãã€ã¢ã¢ã³ãæŒç®åã䜿ãããšã¯åé¡ãããŸããããæšè«ãããåã¯å€ãããŸãããã®æšè«ã®ããã«ããã€ã¢ã¢ã³ãæŒç®åã¯ã¿ãŒã²ããåïŒéåžžã¯å®£èšã®å·ŠåŽïŒãã³ã³ã¹ãã©ã¯ã¿ã®åŒæ°ã®åãå©çšã§ããŸããããããååšããªãå Žåãæãåºãé©çšå¯èœãªåãéåžžã¯Â// DANGEROUS: infers as PriorityQueue<Object>
var itemQueue = new PriorityQueue<>();
Object
 ã«ãã©ãŒã«ããã¯ããŸããããã¯éåžžæå³ãããã®ã§ã¯ãããŸããããžã§ããªãã¯ã¡ãœããã¯åæšè«ãæ¡çšããŠããã®ã§ãããã°ã©ããæ瀺çãªååŒæ°ãæäŸããããšã¯ã»ãšãã©ãããŸãããååãªåæ å ±ãæäŸããå®éã®ã¡ãœããåŒæ°ããªãå Žåããžã§ããªãã¯ã¡ãœããã®æšè«ã¯ã¿ãŒã²ããã®åã«äŸåããŸããÂ
var
 宣èšã§ã¯ãã¿ãŒã²ããã®åããªãããããã€ã€ã¢ã³ãæŒç®åã®å Žåãšåæ§ã®åé¡ãçºçããå¯èœæ§ããããŸãããã€ã€ã¢ã³ãæŒç®åãšãžã§ããªãã¯ã¡ãœããã®äž¡æ¹ã䜿ãã°ãã³ã³ã¹ãã©ã¯ã¿ãŸãã¯ã¡ãœãããžã®å®éã®åŒæ°ãè¿œå ã®åæ å ±ãæäŸããŠãããããæå³ãããåãæšè«ã§ããŸãã// DANGEROUS: infers as List<Object>
var list = List.of();
ãã€ã€ã¢ã³ãæŒç®åããžã§ããªãã¯ã¡ãœãããšå ±ã«Â// OK: itemQueue infers as PriorityQueue<String>
Comparator<String> comp = ... ;
var itemQueue = new PriorityQueue<>(comp);
// OK: infers as List<BigInteger>
var list = List.of(BigInteger.ZERO);
var
 ã䜿çšããå Žåã¯ãæšè«ãããåãããªãã®æå³ãšäžèŽããããã«ãã¡ãœãããŸãã¯ã³ã³ã¹ãã©ã¯ã¿ã®åŒæ°ãåæ
å ±ãååã«æäŸããããã«ããå¿
èŠããããŸããããã§ããªãå Žåã«ã¯ãåäžå®£èšã§Â var
 ãšãã€ã¢ã¢ã³ãæŒç®åãããã¯ãžã§ããªãã¯ã¡ãœããäž¡æ¹ã䜿ããªãã§ãã ãããG7. Take care when using var
with literals.
ããªããã£ããªãªãã©ã«ã¯ã var
 宣èšã®ã€ãã·ã£ã©ã€ã¶ãšããŠäœ¿çšã§ããŸãããããã®ã±ãŒã¹ã§ã¯Â var
 ã䜿çšãããšãååãäžè¬ã«äžè¶³ããããã倧ããªå©ç¹ãåŸããããšã¯èãã«ããã®ã§ãããå€æ°åãæŽåãããªã©ã var
 ãæçšãªå ŽåããããŸããbooleanãcharacterãÂ
long
 ãããã³stringãªãã©ã«ã«åé¡ã¯ãããŸããã ãããã®ãªãã©ã«ããæšè«ãããåã¯æ£ç¢ºãªã®ã§ã var
 ã®æå³ã¯æçœã§ããã€ãã·ã£ã©ã€ã¶ãæ°å€ãç¹ã«æŽæ°ãªãã©ã«ã®å Žåããšããã泚æãå¿ èŠã§ããå·ŠåŽã«æ瀺çãªåãããå Žåãæ°å€ã¯æé»çã«Â// ORIGINAL
boolean ready = true;
char ch = '\ufffd';
long sum = 0L;
String label = "wombat";
// GOOD
var ready = true;
var ch = '\ufffd';
var sum = 0L;
var label = "wombat";
int
 以å€ã®åã«æ¡å€§ãŸãã¯çž®å°ãããŸãã var
 ã䜿çšãããšãå€ã¯æå³ããã«Â int
 ãšããŠæšæž¬ãããããšããããŸããå°æ°ç¹ãªãã©ã«ã¯ã»ãšãã©ã®å Žåæ確ã§ãã// ORIGINAL
byte flags = 0;
short mask = 0x7fff;
long base = 17;
// DANGEROUS: all infer as int
var flags = 0;
var mask = 0x7fff;
var base = 17;
Â// ORIGINAL
float f = 1.0f;
double d = 2.0;
// GOOD
var f = 1.0f;
var d = 2.0;
float
 ïŒæµ®åå°æ°ç¹ïŒãªãã©ã«ã¯ãæé»ã®ãã¡ã«Â double
 ã«åºããå Žåãããããšã®æ³šæããŠãã ããã 3.0f
 ã®ãããªæ瀺çãªfloatãªãã©ã«ã䜿çšããŠÂ double
 å€æ°ãåæåããã®ã¯ããæ°ãå©ããŸãããã double
 å€æ°ã float
 ãã£ãŒã«ãããåæåãããå ŽåããããŸããããã§Â var
 ã«é¢ãã泚æãã¢ããã€ã¹ããŸããïŒå®éã«ã¯ããã®äŸã¯ã¬ã€ãã©ã€ã³G3ã«éåããŠããŸãããªããªããã³ãŒãã®èªè ãæšè«ãããåãèŠãããã«ååãªæ å ±ãã€ãã·ã£ã©ã€ã¶ã«ãªãããã§ããïŒ// ORIGINAL
static final float INITIAL = 3.0f;
...
double temp = INITIAL;
// DANGEROUS: now infers as float
var temp = INITIAL;
Examples
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãÂvar
 ã䜿ãã°æ倧ã®ã¡ãªãããåŸãããå Žæã®äŸãã玹ä»ããŸãã次ã®ã³ãŒãã¯ãå€ããšãÂ
max
 åã®äžèŽãããšã³ããªãMapããåé€ããŸããã¡ãœããã®æè»æ§ãåäžãããããã«ã¯ã€ã«ãã«ãŒãåã®å¢çã䜿çšããŠãããããçµæãšããŠããªãã®åé·æ§ãçããŸããæ®å¿µãªãããããã¯ã€ãã¬ãŒã¿ïŒIteratorïŒã®åããã¹ããããã¯ã€ã«ãã«ãŒãã§ãªããã°ãªããããã®ãã宣èšãããåé·ã«ãªã£ãŠããŸãããã®å®£èšã¯é·ããããããforã«ãŒãã®ããããŒã1è¡ã«åãŸããªããªããã³ãŒããèªã¿ã«ãããªã£ãŠããŸããããã§Â// ORIGINAL
void removeMatches(Map<? extends String, ? extends Number> map, int max) {
for (Iterator<? extends Map.Entry<? extends String, ? extends Number>> iterator =
map.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<? extends String, ? extends Number> entry = iterator.next();
if (max > 0 && matches(entry)) {
iterator.remove();
max--;
}
}
}
var
 ã䜿ããšãããŒã«ã«å€æ°ã®ãã€ãžãŒãªå宣èšãæžããŸãããã®çš®ã®ã«ãŒãã§ã¯ãIteratorããã³Map.Entryã®ããŒã«ã«ã®æ瀺çãªåãæã€å¿
èŠã¯ã»ãšãã©ãããŸãããããã«ãããforã«ãŒãå¶åŸ¡ã1è¡ã«åããããšãã§ããã¯ããã«èªã¿ããããªããŸããtry-with-resourcesã䜿ã£ãŠããœã±ãããã1è¡ã®ããã¹ããèªã¿åãã³ãŒããèããŠã¿ãŸãããããããã¯ãŒã¯ããã³I/O APIã¯ã€ãã£ãªã ãã©ãããããªããžã§ã¯ãã䜿çšããŸããäžéãªããžã§ã¯ãããããããªãœãŒã¹å€æ°ãšããŠå®£èšããŠãåŸç¶ã®ã©ãããŒãéããšãã«ãšã©ãŒãçºçãããé©åã«ã¯ããŒãºããªããã°ãªããŸããããããå®çŸããããã®ããŸã§ã®ã³ãŒãã§ããã°ãå€æ°å®£èšã®å·Šå³ã§ã¯ã©ã¹åãç¹°ãè¿ãå¿ èŠããããçµæãšããŠå€ãã®ãã€ãºãçºçããŸããã// GOOD
void removeMatches(Map<? extends String, ? extends Number> map, int max) {
for (var iterator = map.entrySet().iterator(); iterator.hasNext();) {
var entry = iterator.next();
if (max > 0 && matches(entry)) {
iterator.remove();
max--;
}
}
}
// ORIGINAL
try (InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is, charsetName);
BufferedReader buf = new BufferedReader(isr)) {
return buf.readLine();
}
var
 ã®å©çšã«ããã倧å¹
ã«ãã€ãºãåæžããŸãã// GOOD
try (var inputStream = socket.getInputStream();
var reader = new InputStreamReader(inputStream, charsetName);
var bufReader = new BufferedReader(reader)) {
return bufReader.readLine();
}
Conclusion
宣èšçšéã§Âvar
 ãå©çšãããšãæ··ä¹±ãæžãããšã§ã³ãŒãã®å質ãåäžããŸãããã®ãããããéèŠãªæ
å ±ãéç«ãããããšãã§ããŸãã察ããŠãç¡å·®å¥ã«Â var
 ãæ¡çšãããšãç¶æ³ãæªåããå¯èœæ§ããããŸããé©åã« var
ãå©çšããã°ãããã³ãŒããæ¹åããã®ã«åœ¹ç«ã¡ãç解床ãæãªããã«ã³ãŒããããçããæ確ã«ã§ããŸããReferences
JEP 286: Local-Variable Type Inference
http://openjdk.java.net/jeps/286
Wikipedia: Hungarian Notation
https://en.wikipedia.org/wiki/Hungarian_notation
Bloch, Joshua. Effective Java, 3rd Edition. Addison-Wesley Professional, 2018.
https://www.pearson.com/us/higher-education/program/Bloch-Effective-Java-3rd-Edition/PGM1763855.html