001 /*
002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.io;
027
028 import java.lang.reflect.Field;
029
030 /**
031 * A description of a Serializable field from a Serializable class. An array
032 * of ObjectStreamFields is used to declare the Serializable fields of a class.
033 *
034 * @author Mike Warres
035 * @author Roger Riggs
036 * @version 1.53, 07/05/05
037 * @see ObjectStreamClass
038 * @since 1.2
039 */
040 public class ObjectStreamField implements Comparable<Object> {
041
042 /** field name */
043 private final String name;
044 /** canonical JVM signature of field type */
045 private final String signature;
046 /** field type (Object.class if unknown non-primitive type) */
047 private final Class type;
048 /** whether or not to (de)serialize field values as unshared */
049 private final boolean unshared;
050 /** corresponding reflective field object, if any */
051 private final Field field;
052 /** offset of field value in enclosing field group */
053 private int offset = 0;
054
055 /**
056 * Create a Serializable field with the specified type. This field should
057 * be documented with a <code>serialField</code> tag.
058 *
059 * @param name the name of the serializable field
060 * @param type the <code>Class</code> object of the serializable field
061 */
062 public ObjectStreamField(String name, Class<?> type) {
063 this (name, type, false);
064 }
065
066 /**
067 * Creates an ObjectStreamField representing a serializable field with the
068 * given name and type. If unshared is false, values of the represented
069 * field are serialized and deserialized in the default manner--if the
070 * field is non-primitive, object values are serialized and deserialized as
071 * if they had been written and read by calls to writeObject and
072 * readObject. If unshared is true, values of the represented field are
073 * serialized and deserialized as if they had been written and read by
074 * calls to writeUnshared and readUnshared.
075 *
076 * @param name field name
077 * @param type field type
078 * @param unshared if false, write/read field values in the same manner
079 * as writeObject/readObject; if true, write/read in the same
080 * manner as writeUnshared/readUnshared
081 * @since 1.4
082 */
083 public ObjectStreamField(String name, Class<?> type,
084 boolean unshared) {
085 if (name == null) {
086 throw new NullPointerException();
087 }
088 this .name = name;
089 this .type = type;
090 this .unshared = unshared;
091 signature = ObjectStreamClass.getClassSignature(type).intern();
092 field = null;
093 }
094
095 /**
096 * Creates an ObjectStreamField representing a field with the given name,
097 * signature and unshared setting.
098 */
099 ObjectStreamField(String name, String signature, boolean unshared) {
100 if (name == null) {
101 throw new NullPointerException();
102 }
103 this .name = name;
104 this .signature = signature.intern();
105 this .unshared = unshared;
106 field = null;
107
108 switch (signature.charAt(0)) {
109 case 'Z':
110 type = Boolean.TYPE;
111 break;
112 case 'B':
113 type = Byte.TYPE;
114 break;
115 case 'C':
116 type = Character.TYPE;
117 break;
118 case 'S':
119 type = Short.TYPE;
120 break;
121 case 'I':
122 type = Integer.TYPE;
123 break;
124 case 'J':
125 type = Long.TYPE;
126 break;
127 case 'F':
128 type = Float.TYPE;
129 break;
130 case 'D':
131 type = Double.TYPE;
132 break;
133 case 'L':
134 case '[':
135 type = Object.class;
136 break;
137 default:
138 throw new IllegalArgumentException("illegal signature");
139 }
140 }
141
142 /**
143 * Creates an ObjectStreamField representing the given field with the
144 * specified unshared setting. For compatibility with the behavior of
145 * earlier serialization implementations, a "showType" parameter is
146 * necessary to govern whether or not a getType() call on this
147 * ObjectStreamField (if non-primitive) will return Object.class (as
148 * opposed to a more specific reference type).
149 */
150 ObjectStreamField(Field field, boolean unshared, boolean showType) {
151 this .field = field;
152 this .unshared = unshared;
153 name = field.getName();
154 Class ftype = field.getType();
155 type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
156 signature = ObjectStreamClass.getClassSignature(ftype).intern();
157 }
158
159 /**
160 * Get the name of this field.
161 *
162 * @return a <code>String</code> representing the name of the serializable
163 * field
164 */
165 public String getName() {
166 return name;
167 }
168
169 /**
170 * Get the type of the field. If the type is non-primitive and this
171 * <code>ObjectStreamField</code> was obtained from a deserialized {@link
172 * ObjectStreamClass} instance, then <code>Object.class</code> is returned.
173 * Otherwise, the <code>Class</code> object for the type of the field is
174 * returned.
175 *
176 * @return a <code>Class</code> object representing the type of the
177 * serializable field
178 */
179 public Class<?> getType() {
180 return type;
181 }
182
183 /**
184 * Returns character encoding of field type. The encoding is as follows:
185 * <blockquote><pre>
186 * B byte
187 * C char
188 * D double
189 * F float
190 * I int
191 * J long
192 * L class or interface
193 * S short
194 * Z boolean
195 * [ array
196 * </pre></blockquote>
197 *
198 * @return the typecode of the serializable field
199 */
200 // REMIND: deprecate?
201 public char getTypeCode() {
202 return signature.charAt(0);
203 }
204
205 /**
206 * Return the JVM type signature.
207 *
208 * @return null if this field has a primitive type.
209 */
210 // REMIND: deprecate?
211 public String getTypeString() {
212 return isPrimitive() ? null : signature;
213 }
214
215 /**
216 * Offset of field within instance data.
217 *
218 * @return the offset of this field
219 * @see #setOffset
220 */
221 // REMIND: deprecate?
222 public int getOffset() {
223 return offset;
224 }
225
226 /**
227 * Offset within instance data.
228 *
229 * @param offset the offset of the field
230 * @see #getOffset
231 */
232 // REMIND: deprecate?
233 protected void setOffset(int offset) {
234 this .offset = offset;
235 }
236
237 /**
238 * Return true if this field has a primitive type.
239 *
240 * @return true if and only if this field corresponds to a primitive type
241 */
242 // REMIND: deprecate?
243 public boolean isPrimitive() {
244 char tcode = signature.charAt(0);
245 return ((tcode != 'L') && (tcode != '['));
246 }
247
248 /**
249 * Returns boolean value indicating whether or not the serializable field
250 * represented by this ObjectStreamField instance is unshared.
251 *
252 * @since 1.4
253 */
254 public boolean isUnshared() {
255 return unshared;
256 }
257
258 /**
259 * Compare this field with another <code>ObjectStreamField</code>. Return
260 * -1 if this is smaller, 0 if equal, 1 if greater. Types that are
261 * primitives are "smaller" than object types. If equal, the field names
262 * are compared.
263 */
264 // REMIND: deprecate?
265 public int compareTo(Object obj) {
266 ObjectStreamField other = (ObjectStreamField) obj;
267 boolean isPrim = isPrimitive();
268 if (isPrim != other.isPrimitive()) {
269 return isPrim ? -1 : 1;
270 }
271 return name.compareTo(other.name);
272 }
273
274 /**
275 * Return a string that describes this field.
276 */
277 public String toString() {
278 return signature + ' ' + name;
279 }
280
281 /**
282 * Returns field represented by this ObjectStreamField, or null if
283 * ObjectStreamField is not associated with an actual field.
284 */
285 Field getField() {
286 return field;
287 }
288
289 /**
290 * Returns JVM type signature of field (similar to getTypeString, except
291 * that signature strings are returned for primitive fields as well).
292 */
293 String getSignature() {
294 return signature;
295 }
296 }
|