乾貨!碼出高效,java代碼規範彙總
點點贊 不迷路 文末領取博主精心爲大家準備的面試渡劫大禮包
作爲一名開發人員,當你接手他人的項目時,且當你閱讀他人的代碼時,是否急火攻心,暴跳如雷過,甚至有着大爆粗口的想法,此時的你看着那些密密麻麻的代碼就如同天書一般,羞澀難懂。反正我是有過,你們呢?
Robert Martin曾說過"在代碼閱讀中說髒話的頻率是衡量代碼質量額唯一標準"。當你發現別人看你的代碼時頻頻點頭,甚至投出欣賞的目光,那麼我想此時你的心情也會隨着他人一起愉悅,那種成就感對於程序員來說,是一種說不上的幸福!話不多說,直接乾貨!
本文完全採用阿里巴巴的java開發規範
如果您習慣用IDEA進行代碼開發,推薦一款實用的插件:Alibaba Java Coding Guidelines,可實時幫助我們檢測代碼規範!(本文重點在規範層面,具體用法且見下回分解)
頭一回檢測共發現 32+518+378=928處不規範的地方,甚是可怕!
1.避免用Apache Beanutils進行屬性的copy。
說明
Apache BeanUtils性能較差,可以使用其他方案比如Spring BeanUtils, Cglib BeanCopier。
TestObject a = new TestObject();
TestObject b = new TestObject();
a.setX(b.getX());
a.setY(b.getY());
注意點:
- 從Apache 的拷貝方案切換到Spring 的方案時,需要參數位置進行互換一下
- Spring 的拷貝,需要保證拷貝與被拷貝的對象都擁有對應屬性的 get 和 set 方法
- 拷貝的兩個類必須擁有相同的成員變量
- 如果兩個對象擁有2個屬性完全一致但是類名不同的內部類,會被認爲不是同一個類,不會執行拷貝
舉例:model類轉entity類
private String saveProjectMessage(ProjectModel projectModel) throws Exception{
ProjectEntity projectEntity = new ProjectEntity();
// org.apache.commons.beanutils.BeanUtils;
BeanUtils.copyProperties(projectEntity,projectModel); // 摒棄
org.springframework.beans.BeanUtils.copyProperties(projectModel,projectEntity); //推薦
return commonProjectBiz.saveProject(projectEntity);
}
2.所有的包裝類對象之間值的比較,全部使用equals方法比較
對於Integer var=?在-128至127之間的賦值,Integer對象是在IntegerCache.cache產生,會複用已有對象,這個區間內的Integer值可以直接使用==進行判斷,但是這個區間之外的所有數據,都會在堆上產生,並不會複用已有對象,這是一個大坑,推薦使用equals方法進行判斷。
Integer a = 235;
Integer b = 235;
if (a.equals(b)) {
// code
}
3.Object的equals方法容易拋空指針異常,應使用常量或確定有值的對象來調用equals。
反例
public void f(String str){
if (str.equals("hi")) {
System.out.println("hello world");
}
}
public void f(String str){
String inner = "hi";
if (inner.equals(str)) {
System.out.println("hello world");
}
}
4.集合初始化時,指定集合初始值大小。
說明
HashMap使用如下構造方法進行初始化,如果暫時無法確定集合大小,那麼指定默認值(16)即可。
反例:
Map<String, String> map = new HashMap<String, String>();
正例:
Map<String, String> map = new HashMap<String, String>(16);
5.除常用方法(如getXxx/isXxx)等外,不要在條件判斷中執行復雜的語句,將複雜邏輯判斷的結果賦值給一個有意義的布爾變量,以提高可讀性。
說明
很多if語句內的邏輯相當複雜,閱讀者需要分析條件表達式的最終結果,才能明確什麼樣的條件執行什麼樣的語句,那麼,如果閱讀者分析邏輯表達式錯誤呢?
反例
if ((file.open(fileName, "w") != null) && (...) || (...)) {
// ...
}
正例
boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
//...
}
6.不允許任何魔法值(即未經定義的常量)直接出現在代碼中
反例
if (key.equals("Id#taobao_1")) {
//...
}
正例
String KEY_PRE = "Id#taobao_1";
if (KEY_PRE.equals(key)) {
//...
}
7.Map/Set的key爲自定義對象時,必須重寫hashCode和equals
說明
關於hashCode和equals的處理,遵循如下規則:
1.只要重寫equals,就必須重寫hashCode
2.因爲Set存儲的是不重複的對象,依據hashCode和equals進行判斷,所以Set存儲的對象必須重寫這兩個方法
3.如果自定義對象做爲Map的鍵,那麼必須重寫hashCode和equals。
舉例
// 定義一個車牌類
public class CarNumber {
private String cityCode; // 城市代號
private String number; // 車牌號
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
反例
public class Test {
public static void main(String [] args) {
// key爲自定義類
Map<CarNumber, String> map =new HashMap<>(16);
CarNumber car1 = new CarNumber();
car1.setCityCode("蘇A");
car1.setNumber("11111");
CarNumber car2 = new CarNumber();
car2.setCityCode("蘇A");
car2.setNumber("22222");
map.put(car1, "車牌號1");
map.put(car2, "車牌號2");
// 參數內容和car2對象一樣
CarNumber car3 = new CarNumber();
car3.setCityCode("蘇A");
car3.setNumber("22222");
//控制檯輸出
System.out.println(map.get(car1));
System.out.println(map.get(car2));
System.out.println(map.get(car3));
}
}
輸出結果爲:
正常理解car2&car3對象從hashMap中取值應該是相同的,但如果不重寫hashcode()方法,比較是其地址,car3和car2地址不同,所以不相等!
正例
public class CarNumber {
private String cityCode; // 城市代號
private String number; // 車牌號
//在CarNumber 類中重寫equals()和hashCode()方法;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CarNumber carNumber = (CarNumber) o;
return Objects.equals(cityCode, carNumber.cityCode) &&
Objects.equals(number, carNumber.number);
}
@Override
public int hashCode() {
return Objects.hash(cityCode, number);
}
}
輸出結果爲
原理
- HashMap中的比較key是這樣的,先求出key的hashcode(),比較其值是否相等,若相等再比較equals(),若相等則認爲他們是相等 的。若equals()不相等則認爲他們不相等。
- 如果只重寫hashcode()不重寫equals()方法,當比較equals()時只是看他們是否爲同一對象(即進行內存地址的比較),所以必定要兩個方法一起重寫。
- HashMap用來判斷key是否相等的方法,其實是調用了HashSet判斷加入元素 是否相等。
8.對於Service和DAO類,基於SOA的理念,暴露出來的服務一定是接口,內部的實現類用Impl的後綴與接口區別
反例
public interface DemoService{
void f();
}
正例
public class DemoServiceImpl implements DemoService {
@Override
public void f(){
System.out.println("hello world");
}
}
9.單個方法的總行數不超過80行
說明
除註釋之外的方法簽名、結束右大括號、方法內代碼、空行、回車及任何不可見字符的總行數不超過80行。
10.方法內部單行註釋,在被註釋語句上方另起一行,使用//註釋。方法內部多行註釋使用/* */註釋。注意與代碼對齊。
public void method() {
// Put single line comment above code. (Note: align '//' comment with code)
int a = 3;
/**
* Some description about follow code. (Note: align '/**' comment with code)
*/
int b = 4;
}
11.所有編程相關的命名均不能以下劃線或美元符號開始
反例
private void $test(){
System.out.println("命名不能以美元符號開始")
}
private void _test(){
System.out.println("命名不能以下劃線開始")
}
12.所有的抽象方法(包括接口中的方法)必須要用javadoc註釋、除了返回值、參數、異常說明外,還必須指出該方法做什麼事情,實現什麼功能。
說明:如有實現和調用注意事項,請一併說明。
正例
/**
* fetch data by rule id
*
* @param ruleId 規則Id
* @param page 頁數
* @param jsonContext json字符串
* @return Result<XxxxDO> 出參
*/
Result<XxxxDO> fetchDataByRuleId(Long ruleId, Integer page, String jsonContext);
13.方法名、參數名、成員變量、局部變量都統一使用lowerCamelCase,必須遵從駝峯形式
反例
void selectTODOList(Map<String,Object> todoMap);
正例
void selectTODOList(Map<String,Object> todoMap);
14.包名統一使用小寫,點分隔符之間有且僅有一個自然語義的英語單詞。包名統一使用單數形式,但是類名如果有複數含義,類名可以使用複數形式
正例
com.alibaba.mpp.util / com.taobao.tddl.domain.dto
15.不能使用過時的類或方法
說明
java.net.URLDecoder 中的方法decode(String encodeStr)這個方法已經過時
應該使用雙參數decode(String source, String encode)。
接口提供方既然明確是過時接口,那麼有義務同時提供新的接口;作爲調用方來說,有義務去考證過時方法的新實現是什麼。
16.常量命名應該全部大寫,單詞間用下劃線隔開,力求語義表達完整清楚,不要嫌名字長
17.所有的覆寫方法,必須加@Override註解、
反例
getObject()與get0bject()的問題。
一個是字母的O,一個是數字的0,加@Override可以準確判斷是否覆蓋成功。
另外,如果在抽象類中對方法簽名進行修改,其實現類會馬上編譯報錯。
18.在if/else/for/while/do語句中必須使用大括號,即使只有一行代碼,避免使用下面的形式:if (condition) statements;
反例
if(flag) System.out.println("hello world");
正例
if (flag) {
System.out.println("hello world");
}
19.常量命名應該全部大寫,單詞間用下劃線隔開,力求語義表達完整清楚,不要嫌名字長
public class ConstantNameDemo {
/**
* max stock count
*/
public static final Long MAX_STOCK_COUNT = 50000L;
20.所有的枚舉類型字段必須要有註釋,說明每個數據項的用途。
正例
public enum TestEnum {
/**
* agree
*/
agree("agree"),
/**
* reject
*/
reject("reject");
private String action;
TestEnum(String action) {
this.action = action;
}
public String getAction() {
return action;
}
}
21.所有的類都必須添加創建者信息。
說明
在設置模板時,注意IDEA的@author爲${USER},
而eclipse的@author爲${user},大小寫有區別,而日期的設置統一爲yyyy/MM/dd的格式。
正例
/**
* Demo class
*
* @author java醬
* @date 2020/01/10
*/
public class CodeNoteDemo {
}
結語
好了,本文到這裏節結束啦,希望對大家有所幫助,如果有任何疑問,歡迎評論區留言
最後 : 小編在這裏給大家分享一份 2019年多家公司java面試題整理120多頁pdf文檔的PDF,希望大家在之後的面試中和技術提升能夠事半功倍,需要的朋友們點贊評論喔~
羣號:530720915 點擊加入 進羣驗證“csdn” 獲取
最後
歡迎大家一起交流,整理資料不易,喜歡文章記得點個讚唄,感謝支持!!!