| Home > Advance
Java FAQ
> Java IO FAQ |
| Java-IO |
| |
|
Q .
What is "swizzle", as in "Swizzle this object?"
|
Ans :
It means serialize. To swizzle an object is to recursively
serialize or flatten composed objects.
|
|
Q . I have been using the Serializing capabilities in 1.1 to
save some objects to disk. I added a new field to one of my objects that get serialized and now deserializing my old data no longer works.
I get this exception: java.io.InvalidClassException: MacroData; Local class not compatible
|
Ans
:
You need to add a declaration such as
static final long serialVersionUID = 4021215565287364875L;
in the modified class. The actual value of this long is supplied by the
"serialver" utilitity suppied with the JDK. Any versions of a class
other than the first version require this static to be defined in the
class. This is how versioning is achieved.
|
|
Q .How can I clone using serialization?
|
Ans
:
Look at the code below, It uses serialization to write an object into a byte array, and reads
it back to reconstitute a fresh copy.
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
public class Cloner {
private Cloner() {}
public static Object cloneObject(Object o) throws Exception {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bOut);
out.writeObject(o);
ByteArrayInputStream bIn =
new ByteArrayInputStream(bOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(bIn);
return(in.readObject());
}
public static void main(String args[]) throws Exception {
java.util.Vector v = new java.util.Vector();
v.addElement(new StringBuffer("Hello"));
java.util.Vector vClone =
(java.util.Vector)Cloner.cloneObject(v);
// Changing the StringBuffer int the cloned vector has no
// effect on the original StringBuffer object --
// demonstrating that we have indeed done a deep copy
((StringBuffer)vClone.elementAt(0)).append(" world");
StringBuffer sb = (StringBuffer)v.elementAt(0);
System.out.println(sb.toString());
sb = (StringBuffer)vClone.elementAt(0);
System.out.println(sb.toString());
int array[] = { 1, 2, 3, 4, 5 };
int arrayClone[] = (int [])Cloner.cloneObject(array);
// Again, changes to an element in the cloned array do not
// have any effect on the original
arrayClone[0]++;
System.out.println(array[0]);
System.out.println(arrayClone[0]);
}
}
The main() routine is just a driver. All the cleverness is in the very brief
cloneObject(). It does a "deep" clone, which is what you usually want (though Java gives you a "shallow" clone by default).
|
|
Q .
Why did I lose my updates when I changed data fields in a graph that I was serializing?
|
Ans
:
Quoting from the object serialization specification at:
http://www.javasoft.com/products/jdk/1.1/docs/
guide/serialization/spec/serial-arch.doc.html#4176 The writeObject method serializes the specified object and
traverses its references to other objects in the object graph recursively to create a complete serialized representation of the
graph.
Within a stream, the first reference to any object results in the object being serialized or externalized and the assignment of a
handle for that object. Subsequent references to that object are encoded as the handle.
In other words, changing an object and then writing it again does not really write it twice. Instead it just writes a reference back to the
first occurrence, losing any fields that have changed in the meantime.
There are three ways around this: (1) (inefficient) Reset (or close and reopen) the stream, and start again by writing the new value of the
object. This is drastic -- you are throwing away all the serialization
that you have already done.
(2) (kludgey) Create a new object and write that.
(3) (could be a lot of work) Write your own protocol for object serialization. Have something like a data stream where the contents of
an object are marked by special identifiers. Each "end" of the stream
can decide whether it will use a new object each time or reuse an existing object.
|
|
Q .
What's the hidden size limitation of String serialization?
|
Ans
:
If you wish to Serialize a string, be alert to the restriction
that:
The size of the String, when UTF-encoded, must be < 64Kb So for robust code you have to examine the String once to ensure that
it will be less than 64Kb after encoding, and then have the JVM effectively repeat that work in the process of encoding, when you write
it to an ObjectOutputStream.
A possible workaround that is to strip the string down to "byte[]" and pass it around in RMI that way. The code with this restriction is in
DataOutputStream
public final void writeUTF(String str)
...
[perform the size-after-conversion-to-UTF computation]
...
if (utflen > 65535)
throw new UTFDataFormatException();
...
RMI relies on serialization, so RMI has the same String size limitation.
|
|
Q .
Why can't I serialise a Hashtable?
|
Ans :
Hashtables are serialisable. But remember that Object Serialisation traverses the graph of
referenced objects. If you insert an object into a Hashtable, either as a key or a value, it too
must be serialisable and all objects indirectly referred to from these also.
|
|
Q .
Why can't I serialise an Image?
|
Ans
:
The intention was to do this, but it proved to be a difficult problem to solve in the general
case. It is the peer side image representation which is the problem - it is platform specific.
Now the intention is to wait for enabling support as part of Java2D API. Until then you can do
this yourself, by subclassing Image and implementing readObject and writeObject methods which
transfer the image representation in a portable way. If you have the image as a JPEG or GIF
file, you can write the bytes of the file and reconstruct the file at the remote end. If the
image is in a screen or memory buffer, use java.awt.PixelGrabber to capture the pixels and
serialise this format and reconstruct at the remote end.
|
|
Q .
Why can't I serialise a Frame?
|
Ans
:
You can. But unfortunately if you called setIconImage() then the referenced image will cause
a problem since it is not serialisable.
|
Q . Why can't I serialise a Class object unless the class it represents is itself serialisable.
Since the class Class is serialisable and a class object is just an instance of Class this ought
to work.
|
Ans
:
True, but the reason is the same that Classes for which you want to
serialize instances must have their class marked serialsable. Namely, security. If a class is not marked serialisable
then this implies the programmer does not want it serialized.
|
|
Q .
What about a Class object which represents an interface?
|
Ans
:
Interfaces can extend other interfaces so this is no more of a problem
eg. public interface myInterface extends java.io.Serializable {}
|
|
|