如何将内部没有可序列化字段的 java 对象序列化为字节数组并反序列化该数组以获取原始对象

How to serialize a java object with not Serializable fields inside it into byte array and deserialize the array to get the original object

向社区问好,我最近在我的 java 项目中遇到了序列化和反序列化问题。我有一个 object of a class 包含 other objects as fields.

我想将对象的状态存储到字节数组中然后反序列化字节数组并取回原始对象.但是,构成我的对象字段的对象不是可序列化的(来自第三方库)所以必须首先将它们声明为瞬态的。

现在我的对象已序列化和反序列化,但正如预期的那样,由于我提到的瞬态声明,它的字段为空 before.I 已尝试在我的序列化 class 中本地创建所有元素并为他们分配原始值并继续该过程,但没有任何区别。我在下面引用了我的部分代码,有什么想法吗?预先感谢 :)

这是我的对象的 class 及其字段

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 接口和关联的 readExternal 和 writeExternal 方法。这使您可以完全控制对象的序列化方式。

很明显,您无法序列化包含不可序列化字段的 class。但是您也许可以编写足够的数据来自己重新创建对象。

如果您能够将所需的值复制到 class 内的新 Serializable CustomElement 对象中,那应该会有所作为。使用复制构造函数(如果可用),如果您有足够的可用信息,甚至可以使用反射。

您可以将 Element 字段包装在 class 中,即 Serializable,以便您可以编写它们。此解决方案假定您能够在阅读后调用必要的设置器或构造函数来重新创建 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;
    }
}

现在是一个非常基本的包装器 class 即 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;
     }
}

最后是主要的 class 到 运行 序列化和反序列化逻辑(根据您发布的内容稍作修改):

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;
    }
}