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: |