閱讀文本大概須要3分鐘。java
一、類的命名使用駝峯式命名的規範。
程序員
例如:UserService,可是如下情景例外:DO / BO / PO / DTO / VO。web
例如說:UserPO,StudentPO(PO,VO,DTO,等這類名詞須要全大寫)redis
@Data
@Builder
public class CustomBodyDTO {
private String name;
private String idCode;
private String status;
}
二、若是在模塊或者接口,類,方法中使用了設計模式,那麼請在命名的時候體現出來。sql
例如說:TokenFactory,LoginProxy等。數據庫
public class TokenFactory {
public TokenDTO buildToken(LoginInfo loginInfo) {
String token = UUID.randomUUID().toString();
TokenDTO tokenDTO = TokenDTO.builder()
.token(token)
.createTime(LocalDateTime.now())
.build();
String redisKey = RedisKeyBuilder.buildTokenKey(token);
redisService.setObject(redisKey, loginInfo, Timeout.ONE_DAY * 30 * 2);
log.info("建立token成功|loginInfo={}", loginInfo.toString());
return tokenDTO;
}
}
三、Object 的 equals 方法容易拋空指針異常。設計模式
從源碼來進行分析equals方法是屬於Object類的,若是調用方爲null,那麼天然在運行的時候會拋出空指針異常的狀況。安全
object類中的源碼:微信
public boolean equals(Object obj) {
return (this == obj);
}
爲了不這種現況出現,在比對的時候儘可能將常量或者有肯定值的對象置前。架構
例如說:
正確:「test」.equals(object);
錯誤:object.equals(「test」);
四、對於全部相同類型的包裝類進行比較的時候,都是用equal來進行操做。
對於Integer類來講,當相應的變量數值範圍在-128到127之間的時候,該對象會被存儲在IntegerCache.cache裏面,所以會有對象複用的狀況發生。
因此對於包裝類進行比較的時候,最好統一使用equal方法。
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
五、全部的pojo類中的屬性最好統一使用包裝類屬性類型數據。RPC方法的返回值和參數都統一使用包裝類數據。局部變量中使用基本的數據類型。
對於實際的應用場景來講,例如說一個學生類,當咱們設置裏面的成績字段爲int類型的時候,若是學生沒有考試,那麼這個成績字段應該爲空,可是int默認會賦值爲0,那麼這個時候使用基本數據類型就容易產生誤區,究竟是考了0分,仍是說沒有參加考試。
若是換成使用包裝類Integer類型的話,就能夠經過null值來進行區分了。
六、當pojo類在進行編寫的時候要重寫相應的toString方法,若是該pojo中繼承了另外的一個pojo類,那麼請在相應的tostring函數中加入super.toString()方法。
經過重寫toString方法有利於在日誌輸出的時候查看相應對象的屬性內容進行逐一分析,對於一些有繼承關係的對象而言,加入了super.toString方法更加有助於對該對象的理解和分析。
七、在pojo的getter和setter方法裏面,不要增長業務邏輯的代碼編寫,這樣會增長問題排查的難度。
正確作法:
錯誤作法:
public class User {
private Integer id;
private String username;
public Integer getId() {
return id;
}
public User setId(Integer id) {
this.id = id;
return this;
}
public String getUsername() {
return username;
}
public User setUsername(String username) {
this.username = username;
return this;
}
}public class User {
private Integer id;
private String username;
public Integer getId() {
return id;
}
public User setId(Integer id) {
this.id = id;
return this;
}
public String getUsername() {
return "key-prefix-"+username;
}
public User setUsername(String username) {
this.username = "key-prefix-"+username;
return this;
}
}
八、final 能夠聲明類、成員變量、方法、以及本地變量。
下列狀況使用 final 關鍵字:
不容許被繼承的類,如:String 類。
不容許修改引用的域對象,如:POJO 類的域變量。
不容許被重寫的方法,如:POJO 類的 setter 方法。
不容許運行過程當中從新賦值的局部變量。
避免上下文重複使用一個變量,使用 final 描述能夠強制從新定義一個變量,方便更好地進行重構。
九、對於任何類而言,只要重寫了equals就必須重寫hashcode。
舉例說明:
1)HashSet在存儲數據的時候是存儲不重複對象的,這些對象在進行判斷的時候須要依賴hashcode和equals方法,所以須要重寫。
2)在自定義對象做爲key鍵時,須要重寫hashcode和equals方法,例如說String類就比較適合用於作key來使用。
十、不要在 foreach 循環裏進行元素的 remove/add 操做。
remove 元素請使用 Iterator方式,若是併發操做,須要對 Iterator 對象加鎖。
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (刪除元素的條件) {
iterator.remove();
}
}
十一、使用HashMap的時候,能夠指定集合的初始化大小。
例如說,HashMap裏面須要存放10000個元素,可是因爲沒有進行初始化大小操做,因此在添加元素的時候,hashmap的內部會一直在進行擴容操做,影響性能。
那麼爲了減小擴容操做,能夠在初始化的時候將hashmap的大小設置爲:已知須要存儲的大小/負載因子(0.75)+1
HashMap hashMap=new HashMap<>(13334);
十二、Map類集合中,K/V對於null類型存儲的狀況:
集合名稱 | key | value | 說明 |
---|---|---|---|
HashMap | 容許爲null | 容許爲null | 線程不安全 |
TreeMap | 不容許爲null | 容許爲null | 線程不安全 |
HashTable | 不容許爲null | 不容許爲null | 線程安全 |
ConcurrentHashMap | 不容許爲null | 不容許爲null | 線程安全 |
1三、能夠利用 Set 元素惟一的特性,能夠快速對一個集合進行去重操做,避免使用 List 的contains 方法進行遍歷、對比、去重操做。
通關觀察能夠發現,HashSet底層經過將傳入的值再傳入到一個HashMap裏面去進行操做,進入到HashMap裏面以後,會先經過調用該對象的hashcode來判斷是否有重複的值,若是有再進行equals判斷,若是沒有相同元素則插入處理。
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
1四、線程池不容許使用 Executors 去建立,而是經過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同窗更加明確線程池的運行規則,規避資源耗盡的風險。
錯誤作法:
ExecutorService executors = Executors.newSingleThreadExecutor();
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
對於線程池的參數須要有深刻的理解後,結合實際的機器參數來進行參數設置,從而防止在使用中出現異常。
ExecutorService fixedExecutorService = new ThreadPoolExecutor(
1,
2,
60,
TimeUnit.SECONDS,
linkedBlockingQueue,
new MyThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
ps:使用Executors.new方式建立線程池的缺點:
對於FixedThreadPool 和 SingleThreadPool而言
容許的請求隊列長度爲 Integer.MAX_VALUE,可能會堆積大量的請求,從而致使 OOM。
對於CachedThreadPool 和 ScheduledThreadPool而言
容許的建立線程數量爲 Integer.MAX_VALUE,可能會建立大量的線程,從而致使 OOM。
1五、使用一些日期類的時候,推薦使用LocalDateTime來替代Calendar類,或者說使用Instant來替代掉Date類。
1六、儘可能避免在for循環裏面執行try-catch操做,能夠選擇將try-catch操做放在循環體外部使用。
正確作法:
不推薦作法:
try {
for (int i = 0; i < 100; i++) {
doSomeThing();
}
}catch (Exception e){
e.printStackTrace();
}
for (int i = 0; i < 100; i++) {
try {
doSomeThing();
} catch (Exception e) {
e.printStackTrace();
}
}
1七、對於大段的代碼進行try-catch操做,這是一種不負責任的行爲,將穩定的代碼也都包圍在了try-catch語句塊裏面沒能很好的分清代碼的穩定性範圍。
一般咱們稱在運行中不會出錯的代碼塊爲穩定性代碼,可能會有異常出錯的部分爲非穩定性代碼塊,後者纔是try-catch重點須要關注的對象。
1八、在jdk7以後,對於流這類須要關閉鏈接釋放資源的對象,可使用try-with-resource處理機制來應對。
例以下方代碼:
File file = new File("*****");
try (FileInputStream fin = new FileInputStream(file)) {
//執行相關操做
} catch (Exception e) {
//異常捕獲操做
}
1九、使用ArrayList的時候,若是清楚它的指定大小的話,能夠儘可能在初始化的時候進行大小指定,由於隨着arraylist不斷添加新的元素以後,鏈表的體積會不斷增大擴容。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
20、對於一些短信,郵件,電話,下單,支付等應用場景而言,開發的時候須要設置相關的防重複功能限制,防止出現某些惡意刷單,濫刷這類型狀況。
2一、對於敏感詞彙發表的時候,須要考慮一些文本過濾的策略。
這一塊的功能能夠考慮直接接入市面上已有的成熟的UGC監控服務,或者使用公司內部自研的ugc過濾工具,防止用戶發表惡意評論等狀況出現。
2二、在創建索引的時候,對於索引的命名須要遵循必定的規範:
索引類型 | 命名規則 | 案例 |
---|---|---|
主鍵索引 | pk_字段名,pk是指primary key | pk_order_id |
惟一索引 | uk_字段名,uk是指 unique key | uk_order_id |
普通索引 | idx_字段名,idx是指 index | idx_order_id |
2三、當咱們須要存儲一段文本信息的時候,須要先考慮存儲文本的長度。
若是文本的長度超過了5000,則不建議再選擇使用varchar類型來進行存儲,能夠考慮使用text類型進行數據存儲,這個時候能夠考慮單獨用一張表來進行存儲數據,而且經過一個額外的主鍵id來對應,從而避免影響其餘字段的查詢。
2四、在進行數據庫命名的時候儘可能保證數據庫的名稱和項目工程的名稱一致。
2五、在進行表結構設計的時候,只要具備惟一性質的字段都須要創建惟一索引。
這樣有助於後期進行查詢的時候提升查詢的效率,沒有惟一索引這一層的保障,即便在業務層加入了攔截,可是依然容易形成線上髒數據的產生。
2六、在進行order by這類型sql查詢的時候,須要注意查詢索引的有序性。
關於索引的創建,能夠去了解一下索引的星級評定,例如三星索引。可是我的認爲索引沒有所謂的最優性,須要結合實際的業務場景來設計。
2七、在MySQL中,使用count(*)會統計值爲 NULL 的行,而 count(列名)不會統計此列爲 NULL 值的行。
2八、在進行數據庫存儲引擎選擇的時候,須要結合相關的應用場景來選擇,若是是須要應用在select操做較多的狀況下,能夠選擇使用MyIsAM存儲引擎,若是是對於數據的insert,update,這類修改操做較多的業務場景,則優先推薦使用innodb存儲引擎。目前廣泛互聯網公司都推薦使用innodb較多。
☆
往期精彩
☆
關注我
天天進步一點點
本文分享自微信公衆號 - JAVA樂園(happyhuangjinjin88)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。