1. /*
  2. * @(#)ObjectStreamField.java 1.40 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.io;
  8. import java.lang.reflect.Field;
  9. /**
  10. * A description of a Serializable field from a Serializable class. An array
  11. * of ObjectStreamFields is used to declare the Serializable fields of a class.
  12. *
  13. * @author Mike Warres
  14. * @author Roger Riggs
  15. * @version 1.40, 03/01/23
  16. * @see ObjectStreamClass
  17. * @since 1.2
  18. */
  19. public class ObjectStreamField implements Comparable {
  20. /** field name */
  21. private final String name;
  22. /** canonical JVM signature of field type */
  23. private final String signature;
  24. /** field type (Object.class if unknown non-primitive type) */
  25. private final Class type;
  26. /** whether or not to (de)serialize field values as unshared */
  27. private final boolean unshared;
  28. /** corresponding reflective field object, if any */
  29. private final Field field;
  30. /** offset of field value in enclosing field group */
  31. private int offset = 0;
  32. /**
  33. * Create a Serializable field with the specified type. This field should
  34. * be documented with a <code>serialField</code> tag.
  35. *
  36. * @param name the name of the serializable field
  37. * @param type the <code>Class</code> object of the serializable field
  38. */
  39. public ObjectStreamField(String name, Class type) {
  40. this(name, type, false);
  41. }
  42. /**
  43. * Creates an ObjectStreamField representing a serializable field with the
  44. * given name and type. If unshared is false, values of the represented
  45. * field are serialized and deserialized in the default manner--if the
  46. * field is non-primitive, object values are serialized and deserialized as
  47. * if they had been written and read by calls to writeObject and
  48. * readObject. If unshared is true, values of the represented field are
  49. * serialized and deserialized as if they had been written and read by
  50. * calls to writeUnshared and readUnshared.
  51. *
  52. * @param name field name
  53. * @param type field type
  54. * @param unshared if false, write/read field values in the same manner
  55. * as writeObject/readObject; if true, write/read in the same
  56. * manner as writeUnshared/readUnshared
  57. */
  58. public ObjectStreamField(String name, Class type, boolean unshared) {
  59. if (name == null) {
  60. throw new NullPointerException();
  61. }
  62. this.name = name;
  63. this.type = type;
  64. this.unshared = unshared;
  65. signature = ObjectStreamClass.getClassSignature(type).intern();
  66. field = null;
  67. }
  68. /**
  69. * Creates an ObjectStreamField representing a field with the given name,
  70. * signature and unshared setting.
  71. */
  72. ObjectStreamField(String name, String signature, boolean unshared) {
  73. if (name == null) {
  74. throw new NullPointerException();
  75. }
  76. this.name = name;
  77. this.signature = signature.intern();
  78. this.unshared = unshared;
  79. field = null;
  80. switch (signature.charAt(0)) {
  81. case 'Z': type = Boolean.TYPE; break;
  82. case 'B': type = Byte.TYPE; break;
  83. case 'C': type = Character.TYPE; break;
  84. case 'S': type = Short.TYPE; break;
  85. case 'I': type = Integer.TYPE; break;
  86. case 'J': type = Long.TYPE; break;
  87. case 'F': type = Float.TYPE; break;
  88. case 'D': type = Double.TYPE; break;
  89. case 'L':
  90. case '[': type = Object.class; break;
  91. default: throw new IllegalArgumentException("illegal signature");
  92. }
  93. }
  94. /**
  95. * Creates an ObjectStreamField representing the given field with the
  96. * specified unshared setting. For compatibility with the behavior of
  97. * earlier serialization implementations, a "showType" parameter is
  98. * necessary to govern whether or not a getType() call on this
  99. * ObjectStreamField (if non-primitive) will return Object.class (as
  100. * opposed to a more specific reference type).
  101. */
  102. ObjectStreamField(Field field, boolean unshared, boolean showType) {
  103. this.field = field;
  104. this.unshared = unshared;
  105. name = field.getName();
  106. Class ftype = field.getType();
  107. type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
  108. signature = ObjectStreamClass.getClassSignature(ftype).intern();
  109. }
  110. /**
  111. * Get the name of this field.
  112. *
  113. * @return a <code>String</code> representing the name of the serializable
  114. * field
  115. */
  116. public String getName() {
  117. return name;
  118. }
  119. /**
  120. * Get the type of the field.
  121. *
  122. * @return the <code>Class</code> object of the serializable field
  123. */
  124. public Class getType() {
  125. return type;
  126. }
  127. /**
  128. * Returns character encoding of field type. The encoding is as follows:
  129. * <blockquote><pre>
  130. * B byte
  131. * C char
  132. * D double
  133. * F float
  134. * I int
  135. * J long
  136. * L class or interface
  137. * S short
  138. * Z boolean
  139. * [ array
  140. * </pre></blockquote>
  141. *
  142. * @return the typecode of the serializable field
  143. */
  144. // REMIND: deprecate?
  145. public char getTypeCode() {
  146. return signature.charAt(0);
  147. }
  148. /**
  149. * Return the JVM type signature.
  150. *
  151. * @return null if this field has a primitive type.
  152. */
  153. // REMIND: deprecate?
  154. public String getTypeString() {
  155. return isPrimitive() ? null : signature;
  156. }
  157. /**
  158. * Offset of field within instance data.
  159. *
  160. * @return the offset of this field
  161. * @see #setOffset
  162. */
  163. // REMIND: deprecate?
  164. public int getOffset() {
  165. return offset;
  166. }
  167. /**
  168. * Offset within instance data.
  169. *
  170. * @param offset the offset of the field
  171. * @see #getOffset
  172. */
  173. // REMIND: deprecate?
  174. protected void setOffset(int offset) {
  175. this.offset = offset;
  176. }
  177. /**
  178. * Return true if this field has a primitive type.
  179. *
  180. * @return true if and only if this field corresponds to a primitive type
  181. */
  182. // REMIND: deprecate?
  183. public boolean isPrimitive() {
  184. char tcode = signature.charAt(0);
  185. return ((tcode != 'L') && (tcode != '['));
  186. }
  187. /**
  188. * Returns boolean value indicating whether or not the serializable field
  189. * represented by this ObjectStreamField instance is unshared.
  190. */
  191. public boolean isUnshared() {
  192. return unshared;
  193. }
  194. /**
  195. * Compare this field with another <code>ObjectStreamField</code>. Return
  196. * -1 if this is smaller, 0 if equal, 1 if greater. Types that are
  197. * primitives are "smaller" than object types. If equal, the field names
  198. * are compared.
  199. */
  200. // REMIND: deprecate?
  201. public int compareTo(Object obj) {
  202. ObjectStreamField other = (ObjectStreamField) obj;
  203. boolean isPrim = isPrimitive();
  204. if (isPrim != other.isPrimitive()) {
  205. return isPrim ? -1 : 1;
  206. }
  207. return name.compareTo(other.name);
  208. }
  209. /**
  210. * Return a string that describes this field.
  211. */
  212. public String toString() {
  213. return signature + ' ' + name;
  214. }
  215. /**
  216. * Returns field represented by this ObjectStreamField, or null if
  217. * ObjectStreamField is not associated with an actual field.
  218. */
  219. Field getField() {
  220. return field;
  221. }
  222. /**
  223. * Returns JVM type signature of field (similar to getTypeString, except
  224. * that signature strings are returned for primitive fields as well).
  225. */
  226. String getSignature() {
  227. return signature;
  228. }
  229. }