In java, is it possible to add the Serializable interface to class that doesn't have it at runtime?
There is a class I want to serialize, and it implements Serializable, but one of the objects i开发者_如何学Ct contains does not implement Serializable.
Is there a way to modify the class at runtime to make it implement the Serializable interface so I can serialize it? I can't change it at compile time because its a third party library.
Maybe I would have to use some sort of bytecode writer or something?
EDIT: Both the containing class and contained class are in the 3rd party library so I don't think i can mark something as transient. The containing class is marked as serializable, but it contains an object that is not.
I'm fine with writing a custom serialization method for the class, not sure how I would do this though, would I have to use reflection to get the values of the private variables?
Reading the javadoc for Serializable, I see:
Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
which you could use to manually serialize the uncooperative fields. You could look into using ASM, but it seems hard to believe that it is a maintainable solution.
Fields can be skipped using the transient
modifier. Additional data can be added to the stream by providing readObject
and writeObject
methods. Classes can be subclassed to make them serialisable (though you will need to manage the superclass data), or use a serial proxy (see Effective Java).
First of all, do you really need to do this? Maybe the class in the third-party library is not serializable by design. Even if it's just an omission rather than a deliberate decision, it's easy enough to write a custom serialization method in a helper class. If you have to do this though (like I had to, for something similar). Take a look at Javassist. You can do something like this:
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("mypackage.MyClass");
cc.addInterface(pool.get("java.io.Serializable"))
EDIT: You can use a third-party Serialization API like XStream instead of doing all the dirty work yourself.
If a class is not marked as Serializable that might be of good reasons (take database connections as an example). So first of all make your self clear if you really need to serialize that object as well. If you just need to serialize the surrounding object you may consider marking the contained object as transient.
You could use java.lang.reflect.Proxy to add the Serializable interface to object instances over which you have no life-cycle control (i.e. can't subcalass them) and get them serialized this way. But then you would still not be able to read them back without another hack (i.e. introducing a surrogate class).
I'd recommend to look for an alternative to the Java Serializable mechanism in general. It's pretty much broken by design in several ways.
精彩评论