开发者

Java: Serialization: How to store only a reference, not the content

I'm creating an undo-redo mechanism. To achieve this, I'm using Serialization. Recording the current state by writing it to a ByteArrayOutputStream, using ObjectOutputStream and putting the byte[] into an ArrayList.

But the problem is that, some of the classes are holding a reference/pointer to a BufferedImage. Which I don't want to serialize because of its size (and it doesn't implement Serializable). The reason why I don't want to write it is that it will never change. But it is a different image for each instance of the class, so the static keyword isn't a solution.

My attempt to solve:

开发者_如何学Python
public transient BufferedImage img;

This causes the ObjectOutputStream will not serialize the BufferedImage, but it won't store the reference as well. After deserializing, it will be null.

So, in short, I want to keep the reference to the object, but not the object itself. Which means that, after deserialazing I will be able to use the BufferedImage (because of it isn't removed by the Garbage Collector).

Many thanks.


OK, simple enough, keep a Map<String, BufferedImage> of all images somewhere in your application, let each of your classes serialize the key to its image. And in the readResolve() method, look up the image from the map.


What you are asking for is impossible. Think about it...if you serialized your object and sent it over the internet to a different computer, how on earth would that BufferedImage reference end up pointing to the right object without you sending over the BufferedImage itself as well?

It seems like you're serializing and deserializing within the same Java instance. That's certainly not what Java serialization is meant for; the general case is that the instance that serializes an object will not be the same as the one that deserializes it.

What you can do is write custom (de)serialization logic for your class via readObject() and writeObject(). You could for instance serialize the resource URL or a unique identifier for the image instead of the image itself.


You could add writeObject(java.io.ObjectOutputStream stream) and readObject(java.io.ObjectInputStream stream) methods to your object to customize the serialization process.

Mark the reference transient and then perform logic in writeObject to write a token in the stream to let you identify it later in readObject and re-create it.

See this page for an example of this: http://www.javapractices.com/topic/TopicAction.do?Id=70


In short you can't with only serialization. So I'd suggest getting clever with it. Still continue to mark it transient, but you can hook the serialization process to write out the image when you save it. By adding a methods:

private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException;

private void writeObject(java.io.ObjectOutputStream stream) throws IOException

Those will get called when you deserialize and serialize (respectively). You could then save the file's contents out to a temp folder. Using some sort of unique ID for each instance you could keep separate files on the filesystem so when you undo/redo you would read and write to the same file no matter how many levels of undo/redo you have.

Remember to call defaultWriteObject() and defaultReadObject() inside those methods you're adding so the default serialization is performed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜