java編寫代碼規範
常量和變量
-
直接賦值常量,禁止聲明新對象:
- 直接賦值常量值,只是創建了一個對象引用,而這個對象引用指向常量值。
Long i=1L; String s="abc";
-
當成員變量值無需改變時,儘量定義爲靜態常量
- 在類的每個對象實例中,每個成員變量都有一份副本,而成員靜態常量只有一份實例
public class HttpConnection{ private static final long timeout=5L; }
-
儘量使用基本數據類型,避免自動裝箱和拆箱
- java中的基本數據類型:double,float,long,int,short,char,boolean,分別對應的包裝類Double、Short、Character、Boolean
java支持腳本類型與對象包裝類的自動轉換,被稱爲自動裝箱和拆箱,都需要CPU和內存的自動裝箱和拆箱
-
如果變量的初值會被覆蓋,就沒有必要給變量賦初值
-
儘量使用函數內的基本類型臨時變量:
- 在函數內,基本類型的參數和臨時變量都保存在棧(Stack)中,訪問速度比較快;對象類型的參數和臨時變量的引用都保存在棧(Stack)中,內存都保存在堆(Heap)中,訪問速度比較慢,在類中,任何類型的成員變量都保存在堆(Heap)中,訪問速度比較慢
-
不可變的靜態常量、成員變量,儘量使用非線程安全類
- 不可變的靜態常量,雖然需要支持多線程訪問,也可以使用非線程安全類。
-
null可以賦值給引用變量,但是不能將null賦給基本類型變量
-
不允許使用任何未經定義的常量
-
包裝類型之間的判等用equals而不是==
-
浮點數之間的等值判斷
- 基本類型不用==來比較
- 包裝數據類型不用equals來判斷
-
不能使用一個值爲null的引用類型變量來調用非靜態方法。
-
不能調用非靜態方法來使用一個值爲null的引用類型變量,但是可以使用靜態方法來使用一個值爲null的引用類型變量。
-
在金融計算中必須使用BigDecimal
對象和類
-
禁止使用JSON轉換對象
- JSON提供把對象轉換爲JSON字符串、把JSON字符串轉爲對象的功能,會影響性能
-
儘量不使用反射賦值對象
- 導致性能下降
-
採用Lambda表達式代替內部匿名類
- Lambda表達式在大多數虛擬機中採用invokeDynamic指令實現,相對於匿名內部類在效率上會更高一些
例子:
List<User> userList=new ArrayList<>(); Collections.sort(userList,(User o1,user o2)->{ Long userId1=o1.getId(); Long userId2=o2.getId(); return userId1.compareTo(userId2); });
-
儘量避免定義不必要的子類
- 多一個類就需要多一份類加載,所以儘量避免定義不必要的子類
-
儘量指定類的final修飾符
- 爲類指定final修飾符,可以讓改類不可以被繼承,如果指定了一個類爲final,則該類的所有方法都是fianl的,java編譯器會尋找機會內斂的所有final方法,內斂對於提升java運行效率有很大的作用。
PS:使用Spring的AOP特性時,需要對Bean進行動態代理,如果Bean類添加了final修飾,會導致異常
-
不在foreach循環裏進行元素的remove/add操作,remove元素可以使用Iterator方式,如果併發操作,需要對Iterator對象加鎖。或者將去取出放入一個集合中然後刪除或者增加這個集合。或是使用java8新增方法
-
使用equals時,應使用常量或確定有值得對象來調用equals,避免空指針異常,另外可以使用java.util.Objects的equals方法來避免空指針異常
- 或者使用StringUtils工具類進行判斷
-
成員變量不要使用public修飾,儘量使用private修飾,如果需要被子類繼承,可以用protected修飾
- 如果成員變量設置爲public,那麼每個調用者都可以讀寫它,但如果以private配合getter/setter的形式訪問時,就可以達到“不準訪問”,“只讀訪問”,“讀寫訪問”,“只寫訪問”
class Interviewer {
private Candidate candidate;
public Interviewer (Candidate candidate) {
this.candidate = candidate;
}
public Candidate getCandidate() {
Candidate candidate = new Candidate(this.candidate.getName());
return candidate;
}
}
方法
- 把跟類成員變量無關的方法聲明成靜態方法
- 靜態方法的好處就是不用生成類的實例就可以直接調用,靜態方法不再屬於某個對象,而是屬於它所在的類,只需要通過其類名就可以訪問,不再需要消耗資源去反覆創建對象。即便在類內部的私有方法,如果沒有使用到類成員變量,也可以聲明爲靜態方法。
- 儘量使用基本數據數據類型作爲方法參數類型、返回值類型,避免不必要的裝箱、拆箱和空指針判斷
- 協議方法參數值、返回值非空,避免不必要的空指針判斷
- 協議編程:可以@NonNull和@Nullable標註參數,是否遵循全憑調用者自覺
- 儘量避免不必要的函數封裝
- 方法調用會引起入棧和出棧,導致消耗更多的CPU和內存
表達式
- 儘量使用移位來代替正整數乘除
- 儘量使用StringBuilder進行字符串拼接
- 不要使用“” +轉換字符串,使用String.valueOf
數組
- 不要使用循環拷貝數組,儘量使用System.arraycopy拷貝數組
- 集合轉換爲類型T數組時,儘量傳入空數組T【0】
- 將集合轉化爲數組有兩種方式:toArray(new T【n】)和toArray(new T[0])。
- 集合轉化爲Object數組時,儘量使用toArray()方法
集合
- 初始化集合時,儘量指定集合大小
- 儘量使用Arrays.asList轉化數組爲列表
- 直接迭代需要使用的集合
- 不要使用size方法檢測空,必須使用isEmpty方法檢測空
- 非隨機訪問的List,儘量使用迭代代替隨機訪問
- 儘量使用HashSet判斷值存在
異常
-
儘量避免在finally語句塊中出現運行時錯誤,可以適當添加判斷語句來增加程序的健壯性。
-
try、finally和return:
- try不管有沒有return finally都會執行:避免了在try中return而沒有關閉相關資源的操作。
- try中return的情況下,會將return的值存放到一個本地變量中,finally語句即時對其進行了改變也無法改變返回值
- 但是要是finally中也有return語句的話,會忽略try中的return語句。
緩衝區
- 儘量重複使用同一緩衝區