2
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
28
import java.lang.reflect.Field;
31
* A description of a Serializable field from a Serializable class. An array
32
* of ObjectStreamFields is used to declare the Serializable fields of a class.
36
* @see ObjectStreamClass
39
public class ObjectStreamField
40
implements Comparable<Object>
44
private final String name;
45
/** canonical JVM signature of field type */
46
private String signature;
47
/** field type (Object.class if unknown non-primitive type) */
48
private final Class<?> type;
49
/** whether or not to (de)serialize field values as unshared */
50
private final boolean unshared;
51
/** corresponding reflective field object, if any */
52
private final Field field;
53
/** offset of field value in enclosing field group */
54
private int offset = 0;
57
* Create a Serializable field with the specified type. This field should
58
* be documented with a <code>serialField</code> tag.
60
* @param name the name of the serializable field
61
* @param type the <code>Class</code> object of the serializable field
63
public ObjectStreamField(String name, Class<?> type) {
64
this(name, type, false);
68
* Creates an ObjectStreamField representing a serializable field with the
69
* given name and type. If unshared is false, values of the represented
70
* field are serialized and deserialized in the default manner--if the
71
* field is non-primitive, object values are serialized and deserialized as
72
* if they had been written and read by calls to writeObject and
73
* readObject. If unshared is true, values of the represented field are
74
* serialized and deserialized as if they had been written and read by
75
* calls to writeUnshared and readUnshared.
77
* @param name field name
78
* @param type field type
79
* @param unshared if false, write/read field values in the same manner
80
* as writeObject/readObject; if true, write/read in the same
81
* manner as writeUnshared/readUnshared
84
public ObjectStreamField(String name, Class<?> type, boolean unshared) {
85
if (name == null || type == null) {
86
throw new NullPointerException();
90
this.unshared = unshared;
94
// [IKVM] added lazy signature computation, to avoid the reflection hit, unless we really need it
95
private void lazyInitSignature() {
96
if (signature == null) {
97
signature = getClassSignature(type).intern();
102
* Creates an ObjectStreamField representing a field with the given name,
103
* signature and unshared setting.
105
ObjectStreamField(String name, String signature, boolean unshared) {
107
throw new NullPointerException();
110
this.signature = signature.intern();
111
this.unshared = unshared;
114
switch (signature.charAt(0)) {
115
case 'Z': type = Boolean.TYPE; break;
116
case 'B': type = Byte.TYPE; break;
117
case 'C': type = Character.TYPE; break;
118
case 'S': type = Short.TYPE; break;
119
case 'I': type = Integer.TYPE; break;
120
case 'J': type = Long.TYPE; break;
121
case 'F': type = Float.TYPE; break;
122
case 'D': type = Double.TYPE; break;
124
case '[': type = Object.class; break;
125
default: throw new IllegalArgumentException("illegal signature");
130
* Creates an ObjectStreamField representing the given field with the
131
* specified unshared setting. For compatibility with the behavior of
132
* earlier serialization implementations, a "showType" parameter is
133
* necessary to govern whether or not a getType() call on this
134
* ObjectStreamField (if non-primitive) will return Object.class (as
135
* opposed to a more specific reference type).
137
ObjectStreamField(Field field, boolean unshared, boolean showType) {
139
this.unshared = unshared;
140
name = field.getName();
141
Class<?> ftype = field.getType();
142
type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
143
signature = getClassSignature(ftype).intern();
147
* Get the name of this field.
149
* @return a <code>String</code> representing the name of the serializable
152
public String getName() {
157
* Get the type of the field. If the type is non-primitive and this
158
* <code>ObjectStreamField</code> was obtained from a deserialized {@link
159
* ObjectStreamClass} instance, then <code>Object.class</code> is returned.
160
* Otherwise, the <code>Class</code> object for the type of the field is
163
* @return a <code>Class</code> object representing the type of the
166
public Class<?> getType() {
171
* Returns character encoding of field type. The encoding is as follows:
179
* L class or interface
183
* </pre></blockquote>
185
* @return the typecode of the serializable field
187
// REMIND: deprecate?
188
public char getTypeCode() {
190
return signature.charAt(0);
194
* Return the JVM type signature.
196
* @return null if this field has a primitive type.
198
// REMIND: deprecate?
199
public String getTypeString() {
201
return isPrimitive() ? null : signature;
205
* Offset of field within instance data.
207
* @return the offset of this field
210
// REMIND: deprecate?
211
public int getOffset() {
216
* Offset within instance data.
218
* @param offset the offset of the field
221
// REMIND: deprecate?
222
protected void setOffset(int offset) {
223
this.offset = offset;
227
* Return true if this field has a primitive type.
229
* @return true if and only if this field corresponds to a primitive type
231
// REMIND: deprecate?
232
public boolean isPrimitive() {
234
char tcode = signature.charAt(0);
235
return ((tcode != 'L') && (tcode != '['));
239
* Returns boolean value indicating whether or not the serializable field
240
* represented by this ObjectStreamField instance is unshared.
244
public boolean isUnshared() {
249
* Compare this field with another <code>ObjectStreamField</code>. Return
250
* -1 if this is smaller, 0 if equal, 1 if greater. Types that are
251
* primitives are "smaller" than object types. If equal, the field names
254
// REMIND: deprecate?
255
public int compareTo(Object obj) {
256
ObjectStreamField other = (ObjectStreamField) obj;
257
boolean isPrim = isPrimitive();
258
if (isPrim != other.isPrimitive()) {
259
return isPrim ? -1 : 1;
261
return name.compareTo(other.name);
265
* Return a string that describes this field.
267
public String toString() {
269
return signature + ' ' + name;
273
* Returns field represented by this ObjectStreamField, or null if
274
* ObjectStreamField is not associated with an actual field.
281
* Returns JVM type signature of field (similar to getTypeString, except
282
* that signature strings are returned for primitive fields as well).
284
String getSignature() {
290
* Returns JVM type signature for given class.
292
private static String getClassSignature(Class<?> cl) {
293
StringBuilder sbuf = new StringBuilder();
294
while (cl.isArray()) {
296
cl = cl.getComponentType();
298
if (cl.isPrimitive()) {
299
if (cl == Integer.TYPE) {
301
} else if (cl == Byte.TYPE) {
303
} else if (cl == Long.TYPE) {
305
} else if (cl == Float.TYPE) {
307
} else if (cl == Double.TYPE) {
309
} else if (cl == Short.TYPE) {
311
} else if (cl == Character.TYPE) {
313
} else if (cl == Boolean.TYPE) {
315
} else if (cl == Void.TYPE) {
318
throw new InternalError();
321
sbuf.append('L' + cl.getName().replace('.', '/') + ';');
323
return sbuf.toString();