向社区致敬,我最近在我的java项目中遇到了序列化和反序列化的问题。我有一个类的对象包含其他对象作为字段。
我想将对象的状态存储到一个字节数组中,然后对字节数组进行反序列化并返回原始对象。但是,组成我的对象字段的对象是不可序列化的(来自第三方库),因此必须首先将它们声明为transient。
现在我的对象被序列化和反序列化,但正如预期的那样,由于我之前提到的瞬态声明,它的字段为空。我已经尝试在本地创建我的序列化类的所有元素,并分配给他们的原始值,并继续这个过程,但它没有任何区别。我引用下面我的代码的一部分,有什么想法吗?事先谢谢:)
这是我的对象的类和它的字段
public class AbePublicKey implements java.io.Serializable{
private static final long serialVersionUID = 7526472295622776147L;
public transient Element g;
public transient Element h;
public transient Element f;
public transient Element e_g_g_hat_alpha;
}
这是我的序列化函数
public byte[] PublicKeytoByteArray(AbePublicKey publickey) throws IOException {
KeyAuthority keyauthority = new KeyAuthority();
byte[] bytes = null;
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
publickey.setElements(g, h, f, e_g_g_hat_alpha);
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(publickey);
oos.flush();
bytes = bos.toByteArray();
} finally {
if (oos != null)
oos.close();
}
if (bos != null) {
bos.close();
}
}
return bytes;
}
这是我的反序列化函数
public static AbePublicKey PublicKeyBytestoObject(byte[] publickeybytes) throws IOException, ClassNotFoundException {
AbePublicKey obj = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
bis = new ByteArrayInputStream(publickeybytes);
ois = new ObjectInputStream(bis);
obj = (AbePublicKey) ois.readObject();
} finally {
if (bis != null) {
bis.close();
}
if (ois != null) {
ois.close();
}
}
return obj;
}
如果你想控制一个对象是如何序列化的,实现Externalizable接口和相关的readeexternal和writeExternal方法。这使您可以完全控制对象的序列化方式。
显然你不能序列化一个包含不可序列化字段的类。但是您也许可以编写足够的数据来自己重新创建对象。
如果您能够将所需的值复制到您的类中的新的Serializable CustomElement对象中,那么它应该会有所不同。使用复制构造函数(如果可用),如果有足够的信息,甚至可以使用反射。
您可以将Element
字段包装在Serializable
类中,以便您可以编写它们。这个解决方案假设您能够调用必要的setter或构造函数来重新创建Element
后,您读取它。
下面是一个例子:
非Serializable
的基本元素
public class Element {
private String value;
public Element(){
value = null;
}
public Element(String value){
setValue(value);
}
public void setValue(String value){
this.value = value;
}
public String getValue(){
return value;
}
}
现在是一个非常基本的包装器类Serializable
import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class SerializableElement implements Serializable{
// Generated ID
private static final long serialVersionUID = -6751688345227423403L;
private transient Element element;
public SerializableElement(Element el)
{
element = el;
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException{
out.writeObject(element.getValue());
}
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException{
String elementValue = (String)in.readObject();
element = new Element(elementValue);
}
private void readObjectNoData()
throws ObjectStreamException{
element = null;
}
public Element getElement(){
return element;
}
}
最后一个运行序列化和反序列化逻辑的主类(从你发布的稍微修改):
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializeMain {
public static void main(String[] args) {
SerializableElement serializableElement = new SerializableElement(
new Element("test value"));
try {
byte[] serializedData = storeElement(serializableElement);
SerializableElement loadedElement = loadElement(serializedData);
System.out.println("loadedElement.element.value: "
+ loadedElement.getElement().getValue());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static byte[] storeElement(SerializableElement sElement)
throws IOException {
byte[] bytes = null;
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(sElement);
oos.flush();
bytes = bos.toByteArray();
} finally {
if (oos != null) {
oos.close();
}
if (bos != null) {
bos.close();
}
}
return bytes;
}
public static SerializableElement loadElement(byte[] byteData)
throws IOException, ClassNotFoundException {
SerializableElement obj = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
bis = new ByteArrayInputStream(byteData);
ois = new ObjectInputStream(bis);
obj = (SerializableElement) ois.readObject();
} finally {
if (bis != null) {
bis.close();
}
if (ois != null) {
ois.close();
}
}
return obj;
}
}