Tag Archives: Learning record of Android source code

Java retainAll throws an unsupported operation exception record

Today, when using Java’s retainAll method, I encountered an incredible problem. I reported a problem with JS bridge. But I’m sure that there is no problem with the JS bridge framework. I’ve been running for such a long time. So the problem lies in the use of the retainAll method of the final debug.

After the sentence “retain all”, although the page flashed back directly, there was no error in retain all. So I tried to try catch on the code to see what error was thrown. After debugging, I found that it was the error of unsupported operation exception. This means that the operation is not supported, that is, there is no such method?So I right-click the retainAll method and find that the comment of the retainAll method is as follows:

   /**
     * Retains only the elements in this list that are contained in the
     * specified collection (optional operation).  In other words, removes
     * from this list all of its elements that are not contained in the
     * specified collection.
     *
     * @param c collection containing elements to be retained in this list
     * @return <tt>true</tt> if this list changed as a result of the call
     * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation
     *         is not supported by this list
     * @throws ClassCastException if the class of an element of this list
     *         is incompatible with the specified collection
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if this list contains a null element and the
     *         specified collection does not permit null elements
     *         (<a href="Collection.html#optional-restrictions">optional</a>),
     *         or if the specified collection is null
     * @see #remove(Object)
     * @see #contains(Object)
     */

Then I looked at the object of the array that I called retainAll, which is through the Arrays.asList This is the aslist method, as follows:

 @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

        @Override
        public int size() {
            return a.length;
        }

        @Override
        public Object[] toArray() {
            return a.clone();
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<?extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        @Override
        public E get(int index) {
            return a[index];
        }

        @Override
        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        @Override
        public int indexOf(Object o) {
            E[] a = this.a;
            if (o == null) {
                for (int i = 0; i < a.length; i++)
                    if (a[i] == null)
                        return i;
            } else {
                for (int i = 0; i < a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        @Override
        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }

        @Override
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator(a, Spliterator.ORDERED);
        }

        @Override
        public void forEach(Consumer<?super E> action) {
            Objects.requireNonNull(action);
            for (E e : a) {
                action.accept(e);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            E[] a = this.a;
            for (int i = 0; i < a.length; i++) {
                a[i] = operator.apply(a[i]);
            }
        }

        @Override
        public void sort(Comparator<?super E> c) {
            Arrays.sort(a, c);
        }
    }

That is to say, the array object type generated by aslist is the internal class ArrayList. However, this class inherits the abstractlist and has no retainAll method. The retainAll method is java.util.List Methods in this class, ah Xi.. Solve the case.

So here, I think that I seem to have used the aslist method in other places. It seems that I need to check. After all, there are no add and remove methods.

mark!

Conclusion: This is a good question. It touches the blind area of knowledge and makes me more cautious. In the past, I used to use whatever method I could, but I didn’t really pay attention to the realization of the method. I didn’t know until I reported a mistake. It’s actually a bit fatal for programmers, because problems have already arisen. Therefore, we still need to read more source code and learn to recharge.