@IT·互联网

java.io.NotSerializableException

2017-05-17  本文已影响159人  爱做梦的胖子

5/17/2017 7:15:51 PM


  1. 问题是什么?(What)
    • 未序列化异常
    • 由ArrayList的subList方法引起的
    • SubList类未实现序列化接口Serializable
  2. 为什么会出现这种现象?(Why)
    • 查API
      • 返回的是List的一个视图非实体对象
    List<E> subList(int fromIndex, int toIndex)
    Returns: a view of the specified range within this list
    Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed(支持) by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.
    • 序列化需要使用的是实体对象故序列化时出现异常
  3. 如何解决?(How)
    • new一个对象出来存储子列表数据
    List tmpList = new ArrayList<>(sourceList.subList(fromIndex, endIndex));
    
  4. 修复(Result)
    • 根据错误日志定位缺陷代码位置-->修复
    • 验证功能
  5. 源码
    • SubList是ArrayList的内部类
    • 此对象并未存储数据,只是可以操作原数据
     public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, 0, fromIndex, toIndex);
        }
    
     private class SubList extends AbstractList<E> implements RandomAccess {
            private final AbstractList<E> parent;
            private final int parentOffset;
            private final int offset;
            int size;
    
            SubList(AbstractList<E> parent,
                    int offset, int fromIndex, int toIndex) {
                this.parent = parent;
                this.parentOffset = fromIndex;
                this.offset = offset + fromIndex;
                this.size = toIndex - fromIndex;
                this.modCount = ArrayList.this.modCount;
            }
    
            public E set(int index, E e) {
                rangeCheck(index);
                checkForComodification();
                E oldValue = ArrayList.this.elementData(offset + index);
                ArrayList.this.elementData[offset + index] = e;
                return oldValue;
            }
    
            public E get(int index) {
                rangeCheck(index);
                checkForComodification();
                return ArrayList.this.elementData(offset + index);
            }
    
            public int size() {
                checkForComodification();
                return this.size;
            }
    
            public void add(int index, E e) {
                rangeCheckForAdd(index);
                checkForComodification();
                parent.add(parentOffset + index, e);
                this.modCount = parent.modCount;
                this.size++;
            }
    
            public E remove(int index) {
                rangeCheck(index);
                checkForComodification();
                E result = parent.remove(parentOffset + index);
                this.modCount = parent.modCount;
                this.size--;
                return result;
            }
    
            protected void removeRange(int fromIndex, int toIndex) {
                checkForComodification();
                parent.removeRange(parentOffset + fromIndex,
                                   parentOffset + toIndex);
                this.modCount = parent.modCount;
                this.size -= toIndex - fromIndex;
            }
    
            public boolean addAll(Collection<? extends E> c) {
                return addAll(this.size, c);
            }
    
            public boolean addAll(int index, Collection<? extends E> c) {
                rangeCheckForAdd(index);
                int cSize = c.size();
                if (cSize==0)
                    return false;
    
                checkForComodification();
                parent.addAll(parentOffset + index, c);
                this.modCount = parent.modCount;
                this.size += cSize;
                return true;
            }
    
            public Iterator<E> iterator() {
                return listIterator();
            }
    
            public ListIterator<E> listIterator(final int index) {
                checkForComodification();
                rangeCheckForAdd(index);
                final int offset = this.offset;
    
                return new ListIterator<E>() {
                    int cursor = index;
                    int lastRet = -1;
                    int expectedModCount = ArrayList.this.modCount;
    
                    public boolean hasNext() {
                        return cursor != SubList.this.size;
                    }
    
                    @SuppressWarnings("unchecked")
                    public E next() {
                        checkForComodification();
                        int i = cursor;
                        if (i >= SubList.this.size)
                            throw new NoSuchElementException();
                        Object[] elementData = ArrayList.this.elementData;
                        if (offset + i >= elementData.length)
                            throw new ConcurrentModificationException();
                        cursor = i + 1;
                        return (E) elementData[offset + (lastRet = i)];
                    }
    
                    public boolean hasPrevious() {
                        return cursor != 0;
                    }
    
                    @SuppressWarnings("unchecked")
                    public E previous() {
                        checkForComodification();
                        int i = cursor - 1;
                        if (i < 0)
                            throw new NoSuchElementException();
                        Object[] elementData = ArrayList.this.elementData;
                        if (offset + i >= elementData.length)
                            throw new ConcurrentModificationException();
                        cursor = i;
                        return (E) elementData[offset + (lastRet = i)];
                    }
    
                    public int nextIndex() {
                        return cursor;
                    }
    
                    public int previousIndex() {
                        return cursor - 1;
                    }
    
                    public void remove() {
                        if (lastRet < 0)
                            throw new IllegalStateException();
                        checkForComodification();
    
                        try {
                            SubList.this.remove(lastRet);
                            cursor = lastRet;
                            lastRet = -1;
                            expectedModCount = ArrayList.this.modCount;
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }
    
                    public void set(E e) {
                        if (lastRet < 0)
                            throw new IllegalStateException();
                        checkForComodification();
    
                        try {
                            ArrayList.this.set(offset + lastRet, e);
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }
    
                    public void add(E e) {
                        checkForComodification();
    
                        try {
                            int i = cursor;
                            SubList.this.add(i, e);
                            cursor = i + 1;
                            lastRet = -1;
                            expectedModCount = ArrayList.this.modCount;
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }
    
                    final void checkForComodification() {
                        if (expectedModCount != ArrayList.this.modCount)
                            throw new ConcurrentModificationException();
                    }
                };
            }
    

PS:

 /**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer.
 */
 private transient Object[] elementData;
 /**
 * The size of the ArrayList (the number of elements it contains).
 *
 * @serial
 */
 private int size;
 
 /**
 * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
 * deserialize it).
 */
 private void readObject(java.io.ObjectInputStream s)
 throws java.io.IOException, ClassNotFoundException {
 // Read in size, and any hidden stuff
 s.defaultReadObject();
 
 // Read in array length and allocate array
 int arrayLength = s.readInt();
 Object[] a = elementData = new Object[arrayLength];
 
 // Read in all elements in the proper order.
 for (int i=0; i<size; i++)
 a[i] = s.readObject();
 }
 
 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 array length
 s.writeInt(elementData.length);
 
 // 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();
 }
 
 }
 ```
上一篇下一篇

猜你喜欢

热点阅读