src/share/classes/java/util/Collections.java

Print this page
rev 10180 : 8047795: Collections.checkedList checking bypassed by List.replaceAll
Reviewed-by: duke


3014      */
3015     public static <E> Collection<E> checkedCollection(Collection<E> c,
3016                                                       Class<E> type) {
3017         return new CheckedCollection<>(c, type);
3018     }
3019 
3020     @SuppressWarnings("unchecked")
3021     static <T> T[] zeroLengthArray(Class<T> type) {
3022         return (T[]) Array.newInstance(type, 0);
3023     }
3024 
3025     /**
3026      * @serial include
3027      */
3028     static class CheckedCollection<E> implements Collection<E>, Serializable {
3029         private static final long serialVersionUID = 1578914078182001775L;
3030 
3031         final Collection<E> c;
3032         final Class<E> type;
3033 
3034         void typeCheck(Object o) {
3035             if (o != null && !type.isInstance(o))
3036                 throw new ClassCastException(badElementMsg(o));

3037         }
3038 
3039         private String badElementMsg(Object o) {
3040             return "Attempt to insert " + o.getClass() +
3041                 " element into collection with element type " + type;
3042         }
3043 
3044         CheckedCollection(Collection<E> c, Class<E> type) {
3045             if (c==null || type == null)
3046                 throw new NullPointerException();
3047             this.c = c;
3048             this.type = type;
3049         }
3050 
3051         public int size()                 { return c.size(); }
3052         public boolean isEmpty()          { return c.isEmpty(); }
3053         public boolean contains(Object o) { return c.contains(o); }
3054         public Object[] toArray()         { return c.toArray(); }
3055         public <T> T[] toArray(T[] a)     { return c.toArray(a); }
3056         public String toString()          { return c.toString(); }
3057         public boolean remove(Object o)   { return c.remove(o); }
3058         public void clear()               {        c.clear(); }
3059 
3060         public boolean containsAll(Collection<?> coll) {
3061             return c.containsAll(coll);
3062         }
3063         public boolean removeAll(Collection<?> coll) {
3064             return c.removeAll(coll);
3065         }
3066         public boolean retainAll(Collection<?> coll) {
3067             return c.retainAll(coll);
3068         }


3074             return new Iterator<E>() {
3075                 public boolean hasNext() { return it.hasNext(); }
3076                 public E next()          { return it.next(); }
3077                 public void remove()     {        it.remove(); }};
3078         }
3079 
3080         public boolean add(E e) {
3081             typeCheck(e);
3082             return c.add(e);
3083         }
3084 
3085         private E[] zeroLengthElementArray; // Lazily initialized
3086 
3087         private E[] zeroLengthElementArray() {
3088             return zeroLengthElementArray != null ? zeroLengthElementArray :
3089                 (zeroLengthElementArray = zeroLengthArray(type));
3090         }
3091 
3092         @SuppressWarnings("unchecked")
3093         Collection<E> checkedCopyOf(Collection<? extends E> coll) {
3094             Object[] a = null;
3095             try {
3096                 E[] z = zeroLengthElementArray();
3097                 a = coll.toArray(z);
3098                 // Defend against coll violating the toArray contract
3099                 if (a.getClass() != z.getClass())
3100                     a = Arrays.copyOf(a, a.length, z.getClass());
3101             } catch (ArrayStoreException ignore) {
3102                 // To get better and consistent diagnostics,
3103                 // we call typeCheck explicitly on each element.
3104                 // We call clone() to defend against coll retaining a
3105                 // reference to the returned array and storing a bad
3106                 // element into it after it has been type checked.
3107                 a = coll.toArray().clone();
3108                 for (Object o : a)
3109                     typeCheck(o);
3110             }
3111             // A slight abuse of the type system, but safe here.
3112             return (Collection<E>) Arrays.asList(a);
3113         }
3114 


3470                     typeCheck(e);
3471                     i.set(e);
3472                 }
3473 
3474                 public void add(E e) {
3475                     typeCheck(e);
3476                     i.add(e);
3477                 }
3478 
3479                 @Override
3480                 public void forEachRemaining(Consumer<? super E> action) {
3481                     i.forEachRemaining(action);
3482                 }
3483             };
3484         }
3485 
3486         public List<E> subList(int fromIndex, int toIndex) {
3487             return new CheckedList<>(list.subList(fromIndex, toIndex), type);
3488         }
3489 






3490         @Override
3491         public void replaceAll(UnaryOperator<E> operator) {
3492             list.replaceAll(operator);
3493         }

3494         @Override
3495         public void sort(Comparator<? super E> c) {
3496             list.sort(c);
3497         }
3498     }
3499 
3500     /**
3501      * @serial include
3502      */
3503     static class CheckedRandomAccessList<E> extends CheckedList<E>
3504                                             implements RandomAccess
3505     {
3506         private static final long serialVersionUID = 1638200125423088369L;
3507 
3508         CheckedRandomAccessList(List<E> list, Class<E> type) {
3509             super(list, type);
3510         }
3511 
3512         public List<E> subList(int fromIndex, int toIndex) {
3513             return new CheckedRandomAccessList<>(




3014      */
3015     public static <E> Collection<E> checkedCollection(Collection<E> c,
3016                                                       Class<E> type) {
3017         return new CheckedCollection<>(c, type);
3018     }
3019 
3020     @SuppressWarnings("unchecked")
3021     static <T> T[] zeroLengthArray(Class<T> type) {
3022         return (T[]) Array.newInstance(type, 0);
3023     }
3024 
3025     /**
3026      * @serial include
3027      */
3028     static class CheckedCollection<E> implements Collection<E>, Serializable {
3029         private static final long serialVersionUID = 1578914078182001775L;
3030 
3031         final Collection<E> c;
3032         final Class<E> type;
3033 
3034         E typeCheck(Object o) {
3035             if (o != null && !type.isInstance(o))
3036                 throw new ClassCastException(badElementMsg(o));
3037             return (E) o;
3038         }
3039 
3040         private String badElementMsg(Object o) {
3041             return "Attempt to insert " + o.getClass() +
3042                 " element into collection with element type " + type;
3043         }
3044 
3045         CheckedCollection(Collection<E> c, Class<E> type) {
3046             this.c = Objects.requireNonNull(c, "c");
3047             this.type = Objects.requireNonNull(type, "type");


3048         }
3049 
3050         public int size()                 { return c.size(); }
3051         public boolean isEmpty()          { return c.isEmpty(); }
3052         public boolean contains(Object o) { return c.contains(o); }
3053         public Object[] toArray()         { return c.toArray(); }
3054         public <T> T[] toArray(T[] a)     { return c.toArray(a); }
3055         public String toString()          { return c.toString(); }
3056         public boolean remove(Object o)   { return c.remove(o); }
3057         public void clear()               {        c.clear(); }
3058 
3059         public boolean containsAll(Collection<?> coll) {
3060             return c.containsAll(coll);
3061         }
3062         public boolean removeAll(Collection<?> coll) {
3063             return c.removeAll(coll);
3064         }
3065         public boolean retainAll(Collection<?> coll) {
3066             return c.retainAll(coll);
3067         }


3073             return new Iterator<E>() {
3074                 public boolean hasNext() { return it.hasNext(); }
3075                 public E next()          { return it.next(); }
3076                 public void remove()     {        it.remove(); }};
3077         }
3078 
3079         public boolean add(E e) {
3080             typeCheck(e);
3081             return c.add(e);
3082         }
3083 
3084         private E[] zeroLengthElementArray; // Lazily initialized
3085 
3086         private E[] zeroLengthElementArray() {
3087             return zeroLengthElementArray != null ? zeroLengthElementArray :
3088                 (zeroLengthElementArray = zeroLengthArray(type));
3089         }
3090 
3091         @SuppressWarnings("unchecked")
3092         Collection<E> checkedCopyOf(Collection<? extends E> coll) {
3093             Object[] a;
3094             try {
3095                 E[] z = zeroLengthElementArray();
3096                 a = coll.toArray(z);
3097                 // Defend against coll violating the toArray contract
3098                 if (a.getClass() != z.getClass())
3099                     a = Arrays.copyOf(a, a.length, z.getClass());
3100             } catch (ArrayStoreException ignore) {
3101                 // To get better and consistent diagnostics,
3102                 // we call typeCheck explicitly on each element.
3103                 // We call clone() to defend against coll retaining a
3104                 // reference to the returned array and storing a bad
3105                 // element into it after it has been type checked.
3106                 a = coll.toArray().clone();
3107                 for (Object o : a)
3108                     typeCheck(o);
3109             }
3110             // A slight abuse of the type system, but safe here.
3111             return (Collection<E>) Arrays.asList(a);
3112         }
3113 


3469                     typeCheck(e);
3470                     i.set(e);
3471                 }
3472 
3473                 public void add(E e) {
3474                     typeCheck(e);
3475                     i.add(e);
3476                 }
3477 
3478                 @Override
3479                 public void forEachRemaining(Consumer<? super E> action) {
3480                     i.forEachRemaining(action);
3481                 }
3482             };
3483         }
3484 
3485         public List<E> subList(int fromIndex, int toIndex) {
3486             return new CheckedList<>(list.subList(fromIndex, toIndex), type);
3487         }
3488 
3489         /**
3490          * {@inheritDoc}
3491          *
3492          * @throws ClassCastException if the class of an element returned by the
3493          *         operator prevents it from being added to this collection
3494          */
3495         @Override
3496         public void replaceAll(UnaryOperator<E> operator) {
3497             list.replaceAll(e -> typeCheck(operator.apply(e)));
3498         }
3499 
3500         @Override
3501         public void sort(Comparator<? super E> c) {
3502             list.sort(c);
3503         }
3504     }
3505 
3506     /**
3507      * @serial include
3508      */
3509     static class CheckedRandomAccessList<E> extends CheckedList<E>
3510                                             implements RandomAccess
3511     {
3512         private static final long serialVersionUID = 1638200125423088369L;
3513 
3514         CheckedRandomAccessList(List<E> list, Class<E> type) {
3515             super(list, type);
3516         }
3517 
3518         public List<E> subList(int fromIndex, int toIndex) {
3519             return new CheckedRandomAccessList<>(