jdk/src/java.base/share/classes/java/util/ImmutableCollections.java
changeset 38567 6d4c5a278fff
parent 37802 91fc9ac7b8b3
child 40788 01ffe34b7340
equal deleted inserted replaced
38566:6a1386b76fdd 38567:6d4c5a278fff
    26 package java.util;
    26 package java.util;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.io.InvalidObjectException;
    29 import java.io.InvalidObjectException;
    30 import java.io.ObjectInputStream;
    30 import java.io.ObjectInputStream;
       
    31 import java.io.ObjectOutputStream;
    31 import java.io.ObjectStreamException;
    32 import java.io.ObjectStreamException;
    32 import java.io.Serializable;
    33 import java.io.Serializable;
    33 
    34 
    34 /**
    35 /**
    35  * Container class for immutable collections. Not part of the public API.
    36  * Container class for immutable collections. Not part of the public API.
   605 }
   606 }
   606 
   607 
   607 // ---------- Serialization Proxy ----------
   608 // ---------- Serialization Proxy ----------
   608 
   609 
   609 /**
   610 /**
   610  * Serialization proxy class for immutable collections.
   611  * A unified serialization proxy class for the immutable collections.
       
   612  *
       
   613  * @serial
       
   614  * @since 9
   611  */
   615  */
   612 final class CollSer implements Serializable {
   616 final class CollSer implements Serializable {
   613     private static final long serialVersionUID = 6309168927139932177L;
   617     private static final long serialVersionUID = 6309168927139932177L;
   614 
   618 
   615     static final int IMM_LIST = 1;
   619     static final int IMM_LIST = 1;
   616     static final int IMM_SET = 2;
   620     static final int IMM_SET = 2;
   617     static final int IMM_MAP = 3;
   621     static final int IMM_MAP = 3;
   618 
   622 
   619     private final int flags;
   623     /**
   620     private final Object[] array;
   624      * Indicates the type of collection that is serialized.
   621 
   625      * The low order 8 bits have the value 1 for an immutable
   622     CollSer(int f, Object... a) {
   626      * {@code List}, 2 for an immutable {@code Set}, and 3 for
   623         flags = f;
   627      * an immutable {@code Map}. Any other value causes an
       
   628      * {@link InvalidObjectException} to be thrown. The high
       
   629      * order 24 bits are zero when an instance is serialized,
       
   630      * and they are ignored when an instance is deserialized.
       
   631      * They can thus be used by future implementations without
       
   632      * causing compatibility issues.
       
   633      *
       
   634      * <p>The tag value also determines the interpretation of the
       
   635      * transient {@code Object[] array} field.
       
   636      * For {@code List} and {@code Set}, the array's length is the size
       
   637      * of the collection, and the array contains the elements of the collection.
       
   638      * Null elements are not allowed. For {@code Set}, duplicate elements
       
   639      * are not allowed.
       
   640      *
       
   641      * <p>For {@code Map}, the array's length is twice the number of mappings
       
   642      * present in the map. The array length is necessarily even.
       
   643      * The array contains a succession of key and value pairs:
       
   644      * {@code k1, v1, k2, v2, ..., kN, vN.} Nulls are not allowed,
       
   645      * and duplicate keys are not allowed.
       
   646      *
       
   647      * @serial
       
   648      * @since 9
       
   649      */
       
   650     private final int tag;
       
   651 
       
   652     /**
       
   653      * @serial
       
   654      * @since 9
       
   655      */
       
   656     private transient Object[] array;
       
   657 
       
   658     CollSer(int t, Object... a) {
       
   659         tag = t;
   624         array = a;
   660         array = a;
   625     }
   661     }
   626 
   662 
       
   663     /**
       
   664      * Reads objects from the stream and stores them
       
   665      * in the transient {@code Object[] array} field.
       
   666      *
       
   667      * @serialData
       
   668      * A nonnegative int, indicating the count of objects,
       
   669      * followed by that many objects.
       
   670      *
       
   671      * @param ois the ObjectInputStream from which data is read
       
   672      * @throws IOException if an I/O error occurs
       
   673      * @throws ClassNotFoundException if a serialized class cannot be loaded
       
   674      * @throws InvalidObjectException if the count is negative
       
   675      * @since 9
       
   676      */
       
   677     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
       
   678         ois.defaultReadObject();
       
   679         int len = ois.readInt();
       
   680 
       
   681         if (len < 0) {
       
   682             throw new InvalidObjectException("negative length " + len);
       
   683         }
       
   684 
       
   685         Object[] a = new Object[len];
       
   686         for (int i = 0; i < len; i++) {
       
   687             a[i] = ois.readObject();
       
   688         }
       
   689 
       
   690         array = a;
       
   691     }
       
   692 
       
   693     /**
       
   694      * Writes objects to the stream from
       
   695      * the transient {@code Object[] array} field.
       
   696      *
       
   697      * @serialData
       
   698      * A nonnegative int, indicating the count of objects,
       
   699      * followed by that many objects.
       
   700      *
       
   701      * @param oos the ObjectOutputStream to which data is written
       
   702      * @throws IOException if an I/O error occurs
       
   703      * @since 9
       
   704      */
       
   705     private void writeObject(ObjectOutputStream oos) throws IOException {
       
   706         oos.defaultWriteObject();
       
   707         oos.writeInt(array.length);
       
   708         for (int i = 0; i < array.length; i++) {
       
   709             oos.writeObject(array[i]);
       
   710         }
       
   711     }
       
   712 
       
   713     /**
       
   714      * Creates and returns an immutable collection from this proxy class.
       
   715      * The instance returned is created as if by calling one of the
       
   716      * static factory methods for
       
   717      * <a href="List.html#immutable">List</a>,
       
   718      * <a href="Map.html#immutable">Map</a>, or
       
   719      * <a href="Set.html#immutable">Set</a>.
       
   720      * This proxy class is the serial form for all immutable collection instances,
       
   721      * regardless of implementation type. This is necessary to ensure that the
       
   722      * existence of any particular implementation type is kept out of the
       
   723      * serialized form.
       
   724      *
       
   725      * @return a collection created from this proxy object
       
   726      * @throws InvalidObjectException if the tag value is illegal or if an exception
       
   727      *         is thrown during creation of the collection
       
   728      * @throws ObjectStreamException if another serialization error has occurred
       
   729      * @since 9
       
   730      */
   627     private Object readResolve() throws ObjectStreamException {
   731     private Object readResolve() throws ObjectStreamException {
   628         try {
   732         try {
   629             if (array == null) {
   733             if (array == null) {
   630                 throw new InvalidObjectException("null array");
   734                 throw new InvalidObjectException("null array");
   631             }
   735             }
   632 
   736 
   633             // use low order 8 bits to indicate "kind"
   737             // use low order 8 bits to indicate "kind"
   634             // ignore high order bits
   738             // ignore high order 24 bits
   635             switch (flags & 0xff) {
   739             switch (tag & 0xff) {
   636                 case IMM_LIST:
   740                 case IMM_LIST:
   637                     return List.of(array);
   741                     return List.of(array);
   638                 case IMM_SET:
   742                 case IMM_SET:
   639                     return Set.of(array);
   743                     return Set.of(array);
   640                 case IMM_MAP:
   744                 case IMM_MAP:
   644                         return new ImmutableCollections.Map1<>(array[0], array[1]);
   748                         return new ImmutableCollections.Map1<>(array[0], array[1]);
   645                     } else {
   749                     } else {
   646                         return new ImmutableCollections.MapN<>(array);
   750                         return new ImmutableCollections.MapN<>(array);
   647                     }
   751                     }
   648                 default:
   752                 default:
   649                     throw new InvalidObjectException(String.format("invalid flags 0x%x", flags));
   753                     throw new InvalidObjectException(String.format("invalid flags 0x%x", tag));
   650             }
   754             }
   651         } catch (NullPointerException|IllegalArgumentException ex) {
   755         } catch (NullPointerException|IllegalArgumentException ex) {
   652             InvalidObjectException ioe = new InvalidObjectException("invalid object");
   756             InvalidObjectException ioe = new InvalidObjectException("invalid object");
   653             ioe.initCause(ex);
   757             ioe.initCause(ex);
   654             throw ioe;
   758             throw ioe;