使用原生JS實現一個英雄類Hero, 可以按照以下方式呼叫
ArrayList
是基於陣列實現的,所以支援快速隨機訪問。
RandomAccess:標識該類支援快速隨機訪問
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
陣列預設大小:10
private static final int DEFAULT_CAPACITY = 10;
擴容機制
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
新增元素時確認容量大小: ensureCapacityInternal()
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
容量不夠,擴容: grow()
擴容後的容量:舊容量的1.5倍:oldCapacity + (oldCapacity >> 1)
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); //擴容為原來的1.5倍
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); // 擴容操作要呼叫Arrays.copyOf() 把原陣列複製到新陣列中,但代價高效率低
//一般先指定ArrayList的容量大小,減少擴容操作次數。
}
刪除操作
呼叫System.arraycopy() : 將index+1後的元素複製從index上開始的位置
操作時間複雜度O(N) 代價高
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
序列化
ArrayList基於陣列實現,具有動態擴容機制,儲存的元素不一定都會被使用,沒必要全部進行序列化。
不序列化:儲存元素的陣列 elementData 使用 transient 修飾(transient:預設不會被序列化。)
transient Object[] elementData;
// non-private to simplify nested class access
控制序列化陣列中的元素內容的方法:writeObject() 、 readObject()
//readObject()
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in capacity
s.readInt(); // ignored
if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size);
Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
//writeObject()
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
序列化操作:使用 ObjectOutputStream 的 writeObject() 將物件轉換為位元組流並輸出
writeObject() 方法在傳入的物件存在 writeObject() 的時候會去反射呼叫該物件的 writeObject() 來實現序列化。
User user = new User();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("heyuFile"));
oos.writeObject(user);
反序列化操作:ObjectInputStream 的 readObject() 方法
File file = new File("heyuFile");
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
User user =(User)objectInputStream.readObject();
Fail-Fast 快速失敗:
在做系統設計的時候先考慮異常情況,一旦發生異常,直接停止並上報。
在系統設計中,快速失效系統一種可以立即報告任何可能表明故障的情況的系統。快速失效系統通常設計用於停止正常操作,而不是試圖繼續可能存在缺陷的過程。這種設計通常會在操作中的多個點檢查系統的狀態,因此可以及早檢測到任何故障。快速失敗模組的職責是檢測錯誤,然後讓系統的下一個最高級別處理錯誤。
ConcurrentModificationException異常(CMException):
當方法檢測到物件的併發修改,但不允許這種修改時就丟擲該異常
發生CMException,優先考慮fail-fast有關的情況,實際上這裡並沒有真的發生併發,只是Iterator使用了fail-fast的保護機制,只要他發現有某一次修改是未經過自己進行的,那麼就會丟擲異常。