備注:java 5以后enum是關鍵字
2 ?equals(obj)和hashCode()應該同時被重寫
備注:特殊情況下我們要重寫equals用來實現某些功能,但是同時必須要重寫hashCode;如果obj1.equals(obj2) = true則obj1和obj2對應的內存地址應該相同,hashCode()返回的就是obj的對應的內存地址
3 ?equals(T obj)和compareTo(T obj)應該一起被重寫
備注:嚴格要求來講equals沒有必定要和compareTo一起被重寫,但是從正常的邏輯角度來說obj.equals(obj2) = true應該是obj.compareTo(obj2) = 0
備注:Error和他的子類代表異常的情況,例如內存溢出,通常只有java虛擬機(jvm)會接觸到。
5使用object ==null替代object.equals(null)
備注:如果object為null使用object.equals(null)會拋出空指針異常
備注:如果只有2個分支,使用if else來進行邏輯處理
備注:switch(variable){
case 0:
myLabel:
result = 0 ;
break ;
case 1:…
default:…
}(錯誤的寫法)
switch(variable){
case 0:…
case 1:…
}(正確的寫法)
備注:匿名類代碼長度過長,應該新建一個類(從代碼可讀性的角度)
備注:int[] ??foo();(正確的寫法)int foo()[];(錯誤的寫法)
備注:int[] arr ;(正確的寫法)int arr[] ;(錯誤的寫法)
備注:int a = 10 + 12 ; System.out.println(a);(正確的做法)
System.out.println(10 + 12) ;(錯誤的代碼)
這樣的好處是代碼可讀性強
備注:使用System.arrayCopy方法替代數組循環來拷貝數據2個數組之間的數據
備注:正常情況下代碼不會拋出空指針異常,catch模塊會隱藏原有的異常,導致其他更多微妙的錯誤
16在BigDecimal的構造方法中,避免使用數字的構造方法
備注:new BigDecimal(.1)這個不等于0.1其實是等于.1000000000000000055511151231257827021181583404541015625,因為0.1不等用二進制數來表示,建議使用new BigDecimal(“0.1”)來代替
備注:很多人猜測這是虛擬機拋出的異常,考慮使用IllegalArgumentException(非法參數異常)
備注:不要創建已經存在的整數,如BigInteger.ZERO, java 1.5以后的BigDecimal.ZERO ,BigDecimal.ONE
備注:避免創建布爾值,可以使用Boolean.TRUE /Boolean.FALSE或者Boolean.valueOf();
備注:如果一個對象為null ,調用這個對象的方法會出現空指針異常,有可能是因為你用||替代了&&
備注:boolean result = foo.equalsIgnoreCase(bar)(正確的寫法);
boolean result = foo.toLowerCase().equlas(bar.toLowerCase());(錯誤的寫法)
第二種寫法效率比較低
備注:如果你想要得到某個集合類的數組,你需要傳遞一個指定類的數組參數到toArray方法中,否則你會得到類型不匹配的異常
備注:命名規范一般是大寫字母開頭,一般有camel命名規則
備注:public修飾變量不遵循java的封裝原則
備注:在com.sun.*和sun.*的類是被認為某些方法的具體的實現,但是他們不是java api的一部分,當jdk的版本發生變化,可能會出現問題。
備注:保證資源(像Connection Statement ResultSet)在使用過后關閉
備注:if(condition1 ){ if(condition2) {…}}(錯誤的寫法)
if(condtion1 && condition2) {…}(正確的寫法)
30使用Collection.isEmpty()來判斷Collection是否為空
備注:使用Collection.size()也有同樣的效果,但是Collection.isEmpty()代碼更易讀。
備注:
//correct comment
int a = 1 ;(正確的注釋)
int ?a = 1 ; // wrong comment(錯誤的注釋)
備注:常量命名的正則表達式是^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$
34常量應該被申明為final static而不僅僅是final
備注:如果僅用final修飾變量,對于多個實例化的對象都會增加使用內存。
備注:調用可重寫的構造方法產生對象,可能會存在風險。例如
public class SeniorClass(){
public Senior(){
return toString();
}
public String toString(){
return“Imseniorclass”;
}
}
public class Junior extends SeniorClass(){
public Junior(){
super();
name=”Junior”;
}
public toString(){
return name.toUperCase();
}
}
37邏輯控制語句,if, for, while和switch不應該嵌套太深
備注:嵌套的if, for,while,switch語句嵌套太深,可讀性比較差,最多嵌套長度為3
備注:對于被用@Deprecated標注的代碼,應該最終被刪除
備注:public class foo(
@Deprecated
public void f1(){}(不正確的寫法)
/**
* @Deprecated
*/
public void f2(){}(不正確的寫法)
/**
*@Deprecated
*/
@Deprecated
public void f3(){}(正確的寫法)
)
備注:重復的代碼塊應該被抽出來公用
備注:返回空的數組或者集合,而不是null可以降低復雜度,同時減少空指針異常的概率。
備注:如果finalizer()方法是空的,那么它沒必要出現
備注:空的方法,循環,都應該被刪除
備注:根據oracle的java官方文檔,enumeration接口是復制的iterativeor接口,而且iterator接口中,增加了可供原則的remove方法,以及更短的方法名。
備注:異常意味著當錯誤出現的時候,應用的一個狀態,用final修飾可以確保錯誤的異常狀態不會被改變,例子如下
public class MyException extends Exception{
private int status ;
public MyException(String msg){
super(msg);
}
public int getStatus(){
return status ;
}
public void setStatus(int status ){
this.status = status;
}
}(錯誤的寫法)
public class MyException extends Exception{
private final int status ;
public MyException(String msg){
super(msg);
this.status = status ;
}
public int getStatus(){
return status ;
}
}(正確的寫法)
備注:try{…}catch(Exception e){ LOGGER.info(e)}…(錯誤的寫法)
try{…}catch(Exception e){LOGGER.info(‘context’, e); }(正確的寫法)
47異常類型不應該在catch塊中使用“的instanceof”測試
備注:try{..
}catch(Exception e){
if(e instanceof IOException){…}
if(e instanceof NullPointerException){…}
}(錯誤的寫法)
try{
…
}catch(IOException e){
…
}catch(NullPointerException e){
…
}(正確的寫法)
備注:try {
} catch(Exception e){
}finally{
throw new Exception();
}(錯誤的寫法)
try{
}catch(Exception e){
}finally{
//clean up
}(正確的寫法)
備注:主動調用System.gc()或者Runtime.getRuntime().gc()不是個好主意,因為JVM的供應商,版本都未知
備注:復雜度最高為3
備注:正則表達式^[a-z][a-zA-Z0-9]*$
備注:FIXME標示通常是用來表示該處代碼有bug,但是可能要稍后才進行處理,這條規則是要表示bug要持續追蹤,并確保他不會被忽視
53通用的異常Error,RuntimeException,Throwable不應該向外拋出
備注:
public void foo() throws Throwable{ throw new Exception(“my message”) ; }(錯誤的寫法)
public void foo(){ throw new MyException(“my message exception”)}(正確的寫法)
備注:避免冪等操作,如以下例子
int x = 2 ; x = x ;(錯誤的寫法)
備注:
public void foo() { if(true){doSomething(); }}(錯誤的寫法)
public void foo() {doSomething(); }(正確的寫法)
56 ?if else for while do語句應該使用大括號
備注:
if(condition) foo(); foo1();(錯誤的寫法)
if(condition){
foo();
}
foo1();(正確的寫法)
備注:避免在Stringbuffer中連接非文字或者使用append()方法
備注:避免通過實例化一個類來獲取類例如Class c = new String().getClass() ;應該寫成Class c = String.class;
備注:分支覆蓋率要達到65%
備注:在jdk 1.5版本中使用new Integer()可能會導致內存分配問題,Integer.valueOf()內存分配更加合理
備注:^[A-Z][a-zA-Z0-9]*$
備注:IP地址 應該寫在配置文件中
63應該用java的集合類如List代替特定的類的實現如LinkedList
備注:
public HashSet foo(){
return new HashSet();
}(錯誤的寫法)
public Set foo(){
return new HashSet();
}(正確的寫法)
備注:label在java里面并不經常使用,而且很多開發者并不清楚,他是如何工作的;
備注:
if(condition){
…
}(正確的寫法)
if(condition)
{
…
}(錯誤的寫法)
備注:^[a-z][a-zA-Z0-9]*$
備注:局部變量和類中的屬性一樣的話會導致代碼可讀性變差
class Foo{
int name = 12;
public Foo(int name){
this.name = name;
}(正確的寫法)
public void doSth(){
int name = 123;
System.out.println(name);
}(錯誤的寫法)
}
68 ?Logger應該要用private static final修飾,并且應該共享一個命名約定
備注:LOG(?:GER)?
備注:小寫的”l”,很容易和1混淆
備注:
String[] names = new String[]{“a”,”b”};
for(inti = 0 ; i < names.length ; i++){
if(name[i]== null){
i = names.length ;(錯誤的寫法)
break;(正確的寫法)
}
}
71在循環體中不應該包含超過1個的continue或者break語句
備注:
for(inti = 0 ; i < 10 ; i++){
if(i% 2 == 0){
continue ;
}
if( i % 3 == 0){
continue ;
}
}(錯誤的寫法)
for(inti = 0 ; i < 10 ; i++){
if(i % 2 == 0 || i % 3 == 0){
continue ;
}
}(正確的寫法)
備注:^[a-z][a-zA-Z0-9]*$
備注:
public MyClass{
public String name =“12”;
public MyClass(String name){
name = name ;(錯誤的寫法)
this.name = name ;(正確的寫法)
}
public int add(int a , int b ){
a = a + b ;
return a ;(錯誤的寫法)
return a + b ;(正確的寫法)
}
}
備注:equals方法名應只用于重寫object.equals(o),通過這樣來防止混淆
備注:
public void foo(){
}(錯誤的寫法)
public void foo(){
//do something
}(正確的寫法)
備注:命名為hashCode有2種情況
1是個bug應該加上@Override的注解
2這不是個bug,但會使其他的開發人員混淆
備注:一個方法最多含有7個參數
備注:一個不能被實例化的類,而且沒有任何靜態方法不能被使用
備注:一般按照如下的順序來修飾
public protected private abstract static final transient volatilesynchronizednative strictfp
備注:NCSS原則(沒有注釋的源碼語句)
備注:for(int i = 0;i < 10 ; i++){ ?}(錯誤的寫法)
for(inti = 0 ; i < 10 ; i++);(正確的寫法)
備注:public voidevaluate(int operator){
switch(operator){
case ADD : {
int a = stack.pop();
int b = stack.pop();
int result = a + b ;
stack.push(result );
break ;
}
}
}(錯誤的寫法)
public void evaluate(int operator){
switch(operator){
case ADD:
foo();
break;
}
}
private void foo(){
int a = stack.pop();
int b = stack.pop();
stack.push(a + b);
}
備注:
class Foo{
public Foo(){} ;
public int Foo(){ return 0 ; }(錯誤的寫法)
public int foo(){return 1 ; }(正確的寫法)
}
備注:非靜態類初始化很少被使用,有時候能迷惑開發者。如以下代碼
class MyClass{
private static final Map MY_MAP = new HashMap(){
{
put(“a”,”b”);
}
};(錯誤的寫法)
private static final Map MY_MAP = ImmutableMap.of(“a”,”b”);(正確的寫法)
}
備注:Object.finalize()是通過垃圾回收機制(GC)在對象不被引用的時候進行調用的
public void finalize(int someParam){
}(錯誤的寫法)
public void someBetterName(int param){
}(正確的寫法)
86當重寫Object.finalize()方法時 應該用protected進行修飾
備注:一般而言Object.finalize()只有GC來調用,如果用public進行修飾,他意味著任意一個caller都能調用他
備注:
int myNumber =010 ;(錯誤的寫法)
int myNumber = 8 ;(正確的寫法)
備注:
@Override
public void doSth(){
super.doSth();
}(錯誤的代碼)
@Override
public void doSth(){
super.doSth();
doOther();
}(正確的寫法)
備注:^[a-z]+(\.[a-z][a-z0-9]*)*$
備注:
String a = new Integer(myInteger).toString()(錯誤的寫法)
String a = Integer.toString(myInteger);(正確的寫法)
備注:為了對調用者保持復雜度,方法不應該拋出1個以上的異常
public void delete() throws IOException, SQLException{
}(錯誤的代碼)
public void delete() throws SomeLevelException{
}(正確的代碼)
備注:
if(condition){
return true ;
}else{
return false ;
}(錯誤的寫法)
return condition ;(正確的寫法)
備注:在finally模塊會強制執行所有語句,之前有可能在try或者catch模塊應該返回的是error但是在finally模塊返回的卻是OK
94右括號應該和下一個next ,catch ,finally在同一行
備注:
if(con1){
}
else{
}(錯誤的寫法)
if(con1){
}else{
}(正確的寫法)
備注:
if(con1){
doSomething() ;}
else{ doOther() ; }(錯誤的寫法)
if(con1){
doSomething();
}else{
doOther();
}(正確的寫法)
備注:數組是直接存儲的拷貝的對象,這個是用來防止將來元素發生變化時,數組中的元素也會發生變化
備注:沒有必要在instanceof前面調用null判斷,因為如果對象是null instanceof會返回false
備注:如果一個屬性僅僅被一個方法引用,可以考慮使用局部變量來代替這個屬性
備注:
a =“aa”; b =“bb”(錯誤的寫法)
a =”aa”;
b =”bb”;(正確的寫法)
備注:StringBuffer sb = new StringBuffer(‘c’);這個字符將要被轉換成實例化StringBuffer的大小
備注:避免實例一個String,這不是必須的
備注:
public void foo(){
System.out.println(“action”);
System.out.println(“action”);
System.out.println(“action”);
}(錯誤的寫法)
public void foo(){
String str =“action”;
System.out.println(str);
System.out.println(str);
System.out.println(str);
}(正確的寫法)
備注:避免調用String的toString方法
104 ?String.valueOf()不應該直接加在一個String后面
備注:增加String.valueOf()到一個String后面 減少代碼的可讀性,傳遞到String.valueOf()的參數 應該直接加到String上面
備注:
String myString = null ;
System.out.println(“equals=”+ myString.equal(“foo”))(錯誤的寫法)
String myString = null ;
System.out.println(“equals=”+”foo”.equals(myString));(正確的寫法)
備注:String和其他的Object應該使用equals來進行比較
if(variable==“foo”) {}(錯誤的寫法)
if(“foo”.equals(variable)){}(正確的寫法)
107當重寫Object.clone()方法的時候應該調用super.clone()
備注:根據Oracle的java文檔中關于Object.clone()說明
1 ?x.clone() != x ;
2 ?x.clone().getClass() == x.getClass();
3 ?x.clone().equals(x);
4 ?super.clone()返回一個實例
5 ?super.clone()返回調用者的一個實例
6 ?object.clone()展現的是一個調用者的實例
class BaseClass implements Cloneable{
@Override
public Object clone() throws CloneNotSupportedException {
return new BaseClass() ;(錯誤的寫法)
return super.clone();(正確的寫法)
}
}
108 ?super.finalize()應該在實現object.finalize()后調用
備注:
protected void finalize(){
releaseResource() ;(錯誤的代碼)
}
protected void finalize(){
releaseResource() ;
super.finalize();(正確的寫法)
}
109 ?switch語句應該要添加結束語句(break , return , continue)
備注:switch(variable){
case 0 : doSomething ();(錯誤的寫法阿)
case 1: doOther(); break ;(正確的寫法)
default:
doSomthing();
}
備注:一般一個case最多5行
switch(variable){
case 0 :
System.out.println(“11”);
System.out.println(“11”);
System.out.println(“11”);
break;(正確的寫法)
default:
System.out.println(“11”);
System.out.println(“11”);
System.out.println(“11”);
System.out.println(“11”);
System.out.println(“11”);
break;(錯誤的寫法)
}
備注:
switch(state){
case 0
case 1:
System.out.println(“11”);
break;
}(錯誤的寫法)
switch(state){
default:
System.out.println(“12”);
break;
case 0 :
System.out.println(“12”);
}(錯誤的寫法)
switch(state){
case 0 :
System.out.println(“12”);
break ;
case 1:
break;
default:
System.out.println(“123”);
break;
}(正確的寫法)
112同步類Vector Hashtable StringBuffer不應該被使用
備注:這些Vector Hashtable StringBuffer在早期的JAVA API中是被設計成線程安全的,但是在表現方面并不理想,即使是在單線程的情況下使用,現在可以使用不同步的方法來進行替代,使用ArrayList ,LinkedList代替Vector;HashMap替代Hashtable,StringBuilder替代StringBuffer
113 ?System.exit(…);Runtime.getRuntime().exit(…)不應該被調用
備注:調用System.exit(int status )和Runtime.getRuntime().exit(int status )會導致整個java虛擬機的關閉,要小心使用;例如他不應該由在一個J2EE容器內的應用進行調用。
114 ?System.out和System.err不應該像logger一樣被使用
備注:logger必須滿足的2個條件:用戶能容易的得到日志;日志信息有一定的格式 確保用戶能容易的瀏覽他們
備注:開發人員不應該因為要去閱讀源碼而去設置Tab的長度,tab應該被禁止。
備注:1變量定義2構造方法3函數
public class Foo (){
public static final int OPEN = 4 ;
private int field = 0 ;
public Foo(){}
public void doSomething(){}
}(正確的寫法)
public class Foo (){
public Foo(){}
public void doSomething(){}
public static final int OPEN = 4 ;
private int field = 0 ;
}(錯誤的寫法)
118 ?Object.finalize()方法不應該被調用
備注:根據java的官方文檔Object.finalize()是被GC調用的。
119 ?Object.finalize()方法不應該被重寫
備注:Object.finalize()沒有明確的保證當一個對象的引用被除去的時候,finalize()方法會被立即的調用,其中間隔可能有幾毫秒到幾分鐘,當一些系統資源需要處理一個對象,最好不要依賴這個異步機制來處理它們。
120 ?Thread.run()和Runable.run()不應該直接被調用
備注:使用Thread.run()和Runable.run()的目的是執行代碼在一個獨立的線程,直接調用這些方法并沒有意義,因為這些處理代碼是在當前的線程中。
Thread myThread = new Thread(runnable) ; myThread.run()(錯誤的寫法)
Thread myThread = new Thread(runnable) ; myThread.start()(錯誤的寫法)
備注:Throwable是所有Error和Exception的父類,Error是所有error的父類,不應該由應用進行捕獲,只有Exception和他的子類才能被捕獲
try{…} catch(Throwable t){}(錯誤的寫法)
try{…} catch(Error e){}(錯誤的寫法)
try{…} catch(Exception e){}(正確的寫法)
122 ?Throw.printStackTrace()從來不應該被調用
備注:應該使用logger來代替
備注:拋出相同的異常;RuntimeException或者是他的子類;子類和父類
void foo() throws MyException , MyException{}(錯誤的寫法)
void foo() throws Throwable , Excepion{}(錯誤的寫法)
void foo() throws RuntimeException {}(錯誤的寫法)
void foo() throws ???MyException{}(正確的寫法)
void foo() throws Throwable {}(正確的寫法)
void foo() {}(正確的寫法)
備注:
try{
try{
doSomething();
}catch(RuntimeException r){
}
doSomething();
}catch(RuntimeException e){
}(錯誤的寫法)
private void dedicatedMethod(){
try{
doSomething();
}catch(RuntimeException e){
}
}
try{
dedicatedMethod();
doSomething();
}catch(Exception e){
/** ?*/
}(正確的寫法)
備注:^[A-Z]$
class MyClass(){
?void addAll(Collection c){}
}(錯誤的寫法)
class MyClass(){
?void addAll(Collection c){}
}(正確的寫法)
備注:避免創建不必要的局部變量
備注:避免給一個方法或者構造函數傳遞參數,但是卻不使用這個參數
備注:當檢測到一個局部變量聲明或分配,但未使用。應該刪除這個變量
備注:在接口中的屬性或方法含有默認的修飾符,變量默認的修飾符是public static final方法的修飾符是public abstract,嵌套在接口中的類或者是接口是public static
備注:在檢查完object1 != null調用object1.equals(obj2)而不是obj2.equals(object1)
備注:當檢測到一個私有字段聲明分配一個值,但沒有使用。
備注:沒有被使用的私有方法,意味著dead code而dead code意味著沒有存在的必要,也就是說應該被刪除,這樣能夠減少代碼量,也能減少引入bug
備注:使用Arrays.asList()將數組轉化為List
備注:當檢查單個字符的索引是,使用String.indexOf(char)來獲得,這樣速度快
備注:使用StringBuffer.length()來決定StringBuffer的長度,而不是使用StringBuffer.toString().equals()或者StringBuffer.toString().length()
備注:java文件的導入部分,應該由IDE自動生成而不是依靠人工生成的,沒有使用的或者無用的導入會導致代碼的可讀性降低,應該把這些刪除
備注:對一個不可變對象(BigDecimal或者BigInteger)進行操作,不會改變這個對象本身,操作的結果是一個全新的對象,因此忽視操作的結果是個錯誤
備注:使用括號有時候能引起誤解,所以有的時候應該被刪除。
return 3 ;(正確的寫法)
return (x);(錯誤的寫法)
return (x + 1);(錯誤的寫法)
int ?x = (y/2 + 1) ; (錯誤的寫法)
int ?y = ( 4 + x) *y(正確的寫法)
備注:工具類意味著一群靜態方法的結合,這意味著這個類并不需要被實例化,因次這不應該有公共的構造方法,java默認的給每個類添加一個公共的構造方法,因此至少一個非公用的構造方法應該添加到代碼中
class StringUtils{
public static String add(String s1 , String s2){
return s1 + s2 ;
}
}(錯誤的寫法)
class StringUtils{
private StringUtils(){
}
public static String add(String s1, String s2){
return s1 + s2 ;
}
}(正確的寫法)