sun.com/j2se/1.4.2/docs/guide/serialization/spec/serialTOC.html" > Java Object Serialization Specification. You may set the
serialOverride
configuration property to specify classes that are to be serialized in standard form.
See Persistit JSA 1.1 Object Serialization for more detailed information on these these subjects.
Value as the key of a HashMap or WeakHashMap
It may be useful to build a WeakHashMap associating the serialized content of a Value
with an associated deserialized object to avoid object deserialization overhead or to implement correct identity semantics. Since Value
is mutable it is a poor choice for use as a map key. Instead, an immutable {@link ValueState} should be used to hold an immutablecopy of this state. Value
and ValueState
implement hashCode
and equals
in a compatible fashion so that code similar to the following works as expected:
... Value value = <some value>; if (!map.contains(value)) // uses the transient current state { ValueState vs = new ValueState(value); map.put(vs, object); // uses an immutable copy as the key }
Displayable Format
The {@link #toString()} method of this class attempts to construct ahuman-readable representation of the serialized value. The Tree display panel of the AdminUI utility uses this capability to summarize the contents of values stored in a tree. The string representation is constructed as follows:
- If the state represented by this
Value
is undefined, then return "undefined". - If the state is
null
or a boolean
, return "null" "false", or "true". - If the value represents a primitive type, return the string representation of the value, prefixed by "(byte)", "(short)", "(char)", "(long)", or "(float)" for the corresponding types. Values of type
int
and double
are presented without prefix to reduce clutter. - If the value represents a String, return a modified form of the string enclosed in double quotes. For each character of the string, if it is a double quote replace it by "\"", otherwise if it is outside of the printable ASCII character set replace the character in the modified string by "\b", "\t", "\n", "\r" or "\u0000" such that the modified string would be a valid Java string constant.
- If the value represents a
java.util.Date
, return a formatted representation of the date using the format specified by {@link Key#SDF}. This is a readable format the displays the date with full precision, including milliseconds. - If the value represents an array, return a list of comma-separated element values surrounded by square brackets.
- If the value represents one of the standard
Collection
implementations in the java.util
package, then return a comma-separated list of values surrounded by square brackets. - If the value represents one of the standard
Map
implementations in the java.util
package, then return a comma-separated list of key/value pairs surrounded by square brackets. Each key/value pair is represented by a string in the form key->value. - If the value represents an object of a class for which there is a registered {@link com.persistit.encoding.ValueDisplayer}, invoke the displayer's {@link com.persistit.encoding.ValueDisplayer#display display}method to format a displayable representation of the object.
- If the value represents an object that has been stored using the version 1.1 storage mechanism described object, return the class name of the object followed by a comma-separated tuple, enclosed within curly brace characters, representing the value of each field of the object.
- If the value represents an object encoded through standard Java serialization, return the string "(Serialized-object)" followed by a sequence of hex digits representing the serialized bytes. Note that this process does not attempt to deserialize the object, which might have unintended consequences.
- If the value represents an object that has already been represented within the formatted result - for example, if a
Collection
contain two references to the same object - then instead of creating an additional string representing the second or subsequent instance, emit a back reference pointer in the form @NNN where NNN is the character offset within the displayable string where the first instance was found. (Note: does not apply to strings and the primitive wrapper classes.)
For example, consider a Person class with fields for date of birth, first name, last name, salary and friends, an array of other Person objects. The result returned by {@link #toString} on a Value
representing twoPerson instances, each with just the other as a friend, might appear as follows: (Note, space added for legibility.)
(Person){(Date)19490826000000.000-0400,"Mary","Jones",(long)75000,[ (Person){(Date)19550522000000.000-0400,"John","Smith",(long)68000,[@0]}]}
In this example, John Smith's
friends
array contains a back reference to Mary Jones in the form "@0" because Mary's displayable reference starts at the beginning of the string.
Stream mode
A Value
normally contains just one object or primitive value. In its normal mode of operation, the put
operation overwrites any previously held state, and the get
operation retrieves the one object or primitive value represented by the current state of the Value
. A subsequent invocation of get
returns the same value.
However, at certain times it is useful to store multiple items (fields) together in one Value
object. To allow this, Value
implements an alternative mode of operation called stream mode in which each put
invocation appends a new field to the state rather than replacing the previous state. Similarly, get
operations retrieve sequentially written fields rather than rereading the same field. Stream allows {@link com.persistit.encoding.ValueCoder ValueCoder} implementations to aggregate the multiple fields encapsulatedwithin an encoded value.
Low-Level API
The low-level API allows an application to bypass the encoding and decoding operations described above and instead to operate directly on the byte array stored in the database. This might be appropriate for an existing application that has already implemented its own serialization mechanisms. Applications should use these methods only if there is a compelling design requirement to do so.
The low-level API methods are:
byte[] {@link #getEncodedBytes}int {@link #getEncodedSize}void {@link #setEncodedSize(int)}void {@link #putEncodedBytes(byte[],int,int)}void {@link #copyFromEncodedBytes(byte[],int,int,int)}boolean {@link #ensureFit(int)}
@version 1.1