1. 不可變類
a.add(b); //坑!
BigDecimal爲不可變類, 所以執行運算的結果需要再返回給a
a = a.add(b);
舉一反三
String也是一個不可變類
String s="";
s+"a"; //坑!!
s=s+"a";
事實上jdk的java.lang包中 Boolean, Byte, Character, Double, Float, Integer, Long, Short, String都是不可變類
深入理解
要創建不可變類,要實現下面幾個步驟:
將類聲明爲final,所以它不能被繼承
將所有的成員聲明爲私有的,這樣就不允許直接訪問這些成員
對變量不要提供setter方法
將所有可變的成員聲明爲final,這樣只能對它們賦值一次
通過構造器初始化所有成員,進行深拷貝(deep copy)
在getter方法中,不要直接返回對象本身,而是克隆對象,並返回對象的拷貝
2. ConcurrentModificationException, Map遍歷並刪除某些Key-Value時必須用Iterator!而且僅限刪除
報錯
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922)
at java.util.HashMap$EntryIterator.next(HashMap.java:962)
at java.util.HashMap$EntryIterator.next(HashMap.java:960)
代碼
//如果信號爲空,刪除該條CompanyInfo
for(Map.Entry<Integer, CompanyInfoWithSignalGroup> entry : map.entrySet()){
if(entry.getValue().getSignals().size()==0){
map.remove(entry.getKey());//坑!沒用Iterator
}
}
如果你的 Collection / Map 對象實際只有一個元素的時候, ConcurrentModificationException 異常並不會被拋出。這也就是爲什麼在 javadoc 裏面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
解決方法:在Map或者Collection的時候,不要用它們的API直接修改集合的內容,如果要修改可以用Iterator的remove()方法
由於for-each的寫法,使我們無法獲得iterator對象,所以這種遍歷方式不能進行刪除操作。只好改成了比較土的方法實現了,如下:
Iterator<Map.Entry<Integer, CompanyInfoWithSignalGroup>> it = map.entrySet().iterator();
while(it.hasNext()){
Entry<Integer, CompanyInfoWithSignalGroup> entry=it.next();
if(entry.getValue().getSignals().size()==0){
it.remove();
}
}
3. SQL語句中的單引號
java中字符串的單引號要用單引號轉義,而不是通常的反斜槓
String str = "''s'', \'s\'"; //'s', s
SQL中的應用:
String sqlTemplate =
" INSERT INTO ebd_exclude_company_detail " +
" (company_id, company_full_name, company_short_name, company_type, company_source) " +
" VALUES ({0}, ''{1}'', ''{2}'', ''{3}'', ''{4}''); ";
//ls是List<String>
String sql = MessageFormat.format(sqlTemplate, ls.toArray(new String[ls.size()])); // 該方法參數只接受Array,不支持List
4. 隕石坑——List.addAll(anotherList)
淺拷貝, 類似的還有:
new List<>(anotherList)
深拷貝必須重寫clone方法, 參考Java中如何克隆集合——ArrayList和HashSet深拷貝
1)Employee實現Cloneable接口
2)爲Employee類增加下面的clone()方法
@Override
protected Employee clone() {
Employee clone = null;
try{
clone = (Employee) super.clone();
}catch(CloneNotSupportedException e){
throw new RuntimeException(e); // won't happen
}
return clone;
}
3)不使用拷貝構造函數,使用下面的代碼來深拷貝集合
Collection<Employee> copy = new HashSet<Employee>(org.size());
Iterator<Employee> iterator = org.iterator();
while(iterator.hasNext()){
copy.add(iterator.next().clone());
}
4)運行相同的代碼更改原始集合,克隆集合不會也被更改。
- Original Collection after modification [Joe: staff, Tim: staff, Frank: staff]
- Copy of Collection without modification [Frank: Developer, Joe: Manager, Tim: Develope]
5) 重要!如果Employee的成員變量包括list等集合類,需要在重寫的clone方法中單獨做深拷貝
思考:Java中集合的深拷貝比較複雜,如果遇到嵌套的List,那麼重寫Cloneable接口還不能實現完整的深拷貝。不如新建一個集合,手動新建元素實現深拷貝。