我們都知道當要將array轉換成List來使用時,可以使用Arrays.asList來轉換,但是這時回傳
回去的並不是java.util.ArrayList而是Arrays的內部私有類別ArrayList,它也繼承了ArrayList
的父類別AbstractList,因此原則上ArrayList的method幾乎它都可以呼叫! (如add, remove, size
等)
不過,但它繼承了AbstractList卻沒有全部都override掉,因此當呼叫add method想要增加
element時,卻拋出了java.lang.UnsupportedOperationException在
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at ArrayList_sample.main(ArrayList_sample.java:37)
也就是原本AbstractList內的add method本身就寫了throw new UnsupportedOperationException();
而這個內部定義的ArrayList又沒有覆寫掉add,因此,呼叫add會呼叫到父類別本身的。
由Arrays.asList回傳的list來看,本身它就不支援add, remove動作來動態增加list,純粹有點像
是在操作array本身,也就是當呼叫get method,也只是以array來取值回傳,如下:
public E get(int index) {
return a[index];
}
也如同官網上所敘述的當使用asList時
Returns a fixed-size list backed by the specified array.
此時我們能想到的就是擺脫以AbstractList為呼叫的method實體,若是ArrayList的話就能
夠以它覆寫過後重新定義的method來操作
因此我用list呼叫了subList(AbstractList method)所回傳的List,但在呼叫add後還是出現一樣
的exception。原因出在AbstractList下的subList會判斷當下的實體型態,因為此list為
Arrays.java - 2834行
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
....
因此勢必在this instanceof RandomAccess會成立
public List<E> subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
再追朔到
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
super(list, fromIndex, toIndex);
}
public List<E> subList(int fromIndex, int toIndex) {
return new RandomAccessSubList<>(this, fromIndex, toIndex);
}
}
super又呼叫SubList做初始化,因此帶進來的實體已為AbstractList內部類別SubList
在呼叫add之後,由於SubList沒定義,因此呼叫AbstractList的
public boolean add(E e) {
add(size(), e);
return true;
}
再來呼叫的add(size(), e);已是SubList的method而非AbstractList的
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
l.add(index+offset, element);
this.modCount = l.modCount;
size++;
}
一切看起來好像已有動態list的樣子,但當呼叫l.add時又回到呼叫AbstractList的method
導致又拋出例外,原因在於呼叫super帶入的第一個參數的實體為AbstractList
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
.....
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
最後,能夠處理的方式還可以利用一開始的list (Arrays.asList所回傳)透過新new一ArrayList
做初始化帶入值得到新的List
List<String> newList = new ArrayList<String>(list);
如此一來newList就可以使用ArrayList內的相關method進行動態操作了
PS. 以上的片段程式碼出自Java Source code
回去的並不是java.util.ArrayList而是Arrays的內部私有類別ArrayList,它也繼承了ArrayList
的父類別AbstractList,因此原則上ArrayList的method幾乎它都可以呼叫! (如add, remove, size
等)
不過,但它繼承了AbstractList卻沒有全部都override掉,因此當呼叫add method想要增加
element時,卻拋出了java.lang.UnsupportedOperationException在
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at ArrayList_sample.main(ArrayList_sample.java:37)
也就是原本AbstractList內的add method本身就寫了throw new UnsupportedOperationException();
而這個內部定義的ArrayList又沒有覆寫掉add,因此,呼叫add會呼叫到父類別本身的。
由Arrays.asList回傳的list來看,本身它就不支援add, remove動作來動態增加list,純粹有點像
是在操作array本身,也就是當呼叫get method,也只是以array來取值回傳,如下:
public E get(int index) {
return a[index];
}
也如同官網上所敘述的當使用asList時
Returns a fixed-size list backed by the specified array.
此時我們能想到的就是擺脫以AbstractList為呼叫的method實體,若是ArrayList的話就能
夠以它覆寫過後重新定義的method來操作
因此我用list呼叫了subList(AbstractList method)所回傳的List,但在呼叫add後還是出現一樣
的exception。原因出在AbstractList下的subList會判斷當下的實體型態,因為此list為
Arrays.java - 2834行
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
....
因此勢必在this instanceof RandomAccess會成立
public List<E> subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
再追朔到
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
super(list, fromIndex, toIndex);
}
public List<E> subList(int fromIndex, int toIndex) {
return new RandomAccessSubList<>(this, fromIndex, toIndex);
}
}
super又呼叫SubList做初始化,因此帶進來的實體已為AbstractList內部類別SubList
在呼叫add之後,由於SubList沒定義,因此呼叫AbstractList的
public boolean add(E e) {
add(size(), e);
return true;
}
再來呼叫的add(size(), e);已是SubList的method而非AbstractList的
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
l.add(index+offset, element);
this.modCount = l.modCount;
size++;
}
一切看起來好像已有動態list的樣子,但當呼叫l.add時又回到呼叫AbstractList的method
導致又拋出例外,原因在於呼叫super帶入的第一個參數的實體為AbstractList
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
.....
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
最後,能夠處理的方式還可以利用一開始的list (Arrays.asList所回傳)透過新new一ArrayList
做初始化帶入值得到新的List
List<String> newList = new ArrayList<String>(list);
如此一來newList就可以使用ArrayList內的相關method進行動態操作了
PS. 以上的片段程式碼出自Java Source code
留言
張貼留言