Java 序列化对象(如区域)

标签 java serialization area

我已经阅读了一些有关 3rd 方序列化方法(例如 JSON)的内容,但想知道是否有其他方法可以序列化对象(例如未实现可序列化的区域)。换句话说,JSON 是序列化此类对象的最佳方式吗?

编辑:抛出不可序列化异常

public class Test {



public static void main(String[] args) throws Exception {
    Pojo pojo = new Pojo(new Area()); // The original object, NOT SERIALIZABLE !
    byte[] pojoBytes = Serializer.serialize(pojo); // Serialize
    pojo = (Pojo) Serializer.deserialize(pojoBytes); // Deserialize
    System.out.println(pojo); // Good as new !
}

} 

public class Pojo implements Serializable {
private final Area msg;
public Pojo(Area msg) {
    this.msg = msg;
}
public Area getMsg() {
    return msg;
}
public String toString() {
    return "Pojo says : " + msg;
}
}

public class Serializer {

public static byte[] serialize(Object o) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileOutputStream fileOut = new FileOutputStream("Test.ser");
ObjectOutputStream oos = new SurrogateObjectOutputStream(fileOut); // Magically handle Pojos !
oos.writeObject(o);
oos.flush();
oos.close();
return baos.toByteArray();
}

public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
    ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
    FileInputStream fileIn = new FileInputStream("Test.ser");
    ObjectInputStream ois = new ObjectInputStream(fileIn);
    Object o = ois.readObject();
    bais.close();
    return o;
}

}

public class SurrogateObjectOutputStream extends ObjectOutputStream {

public SurrogateObjectOutputStream(OutputStream out) throws IOException {
    super(out);
    enableReplaceObject(true);
}

protected SurrogateObjectOutputStream() throws IOException, SecurityException {
    super();
    enableReplaceObject(true);
}

@Override
protected Object replaceObject(Object obj) throws IOException {
    if (obj instanceof Pojo) {
        return new PojoSurrogate((Pojo) obj);
    } else return super.replaceObject(obj);
}

}

public class PojoSurrogate implements Serializable {

private Area foo;

public PojoSurrogate(Pojo pojo) {
    this.foo = pojo.getMsg();
}   

private Object readResolve() throws ObjectStreamException {
    return new Pojo(foo);
}

}

最佳答案

这取决于,如果您想在另一个程序或另一种语言中使用该对象,那么是的 JSON 是可行的方法(或 XML)。

但是,如果您想在另一个 JAVA 程序中重用该对象,那么我想寻找一种方法来使可序列化会更方便>对象可序列化。

我还没有测试过,但我在 this blog (which is in French, sorry) 中找到了一个有前途的解决方案。我会尽力总结一下:

你拥有什么

假设你有一个类名 Pojo 并且你想序列化它,尽管你不知道它是否可序列化。

public final class Pojo {

    private final String msg;

    public Pojo(String msg) {
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public String toString() {
        return "Pojo says : " + msg;
    }
}

您需要什么

您需要的是一个充当代理的新类,它将采用真实 Pojo 的成员变量,并且简单地< em>更换它。

public class PojoSurrogate implements Serializable {

    private String foo;

    public PojoSurrogate(Pojo pojo) {
        this.foo = pojo.getMsg();
    }   

    private Object readResolve() throws ObjectStreamException {
        return new Pojo(foo);
    } 
}

最后一个方法(readResolve())最终会在稍后返回新的Pojo

您需要的另一件事是您自己的ObjectOutputStream代理版本:

public class SurrogateObjectOutputStream extends ObjectOutputStream {

    public SurrogateObjectOutputStream(OutputStream out) throws IOException {
        super(out);
        enableReplaceObject(true);
    }

    protected SurrogateObjectOutputStream() throws IOException, SecurityException {
        super();
        enableReplaceObject(true);
    }

    @Override
    protected Object replaceObject(Object obj) throws IOException {
        if (obj instanceof Pojo) {
            return new PojoSurrogate((Pojo) obj);
        } else return super.replaceObject(obj);
    } 
}

这里最后一个方法 replaceObject() 将发挥魔力,将 Pojo 转换为可序列化版本 PojoSurrogate 以存储所有以字节为单位的信息。

像这样序列化

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new SurrogateObjectOutputStream(baos); 
oos.writeObject(o);
oos.flush();
oos.close();

byte[] serializedPojo = baos.toByteArray();  

正常反序列化

ObjectInputStream bais = new ObjectInputStream(new ByteArrayInputStream( serializedPojo ));
Pojo myNewPojo = (Pojo) bais.readObject();
bais.close();

抱歉,答案很长..我希望我没有错过该博客中的任何超酷内容,在该博客中可以更轻松地创建更具可扩展性的解决方案..希望这无论如何都会有所帮助!

[编辑:]

我用一个 Area 对象尝试了你的代码,这就是我如何让一些东西起作用(尽管我不确定这是否真的适用于所有 Areas,所以你可能需要测试是否反序列化后您的区域仍然具有相同的特征)

区域代理

public class AreaSurrogate implements Serializable {

    private final Rectangle bounds;

    public AreaSurrogate(Area area) {
        this.bounds = area.getBounds();
    }

    private Object readResolve() throws ObjectStreamException {
        return new Area(bounds);
    }
}    

代理输出流

public class SurrogateOutputStream extends ObjectOutputStream {

    public SurrogateOutputStream(OutputStream out) throws IOException {
        super(out);
        enableReplaceObject(true);
    }

    protected SurrogateOutputStream() throws IOException, SecurityException {
        super();
        enableReplaceObject(true);
    }

    @Override
    protected Object replaceObject(Object obj) throws IOException {
        if (obj instanceof Area) {
            return new AreaSurrogate((Area) obj);
        } else {
            return super.replaceObject(obj);
        }
    }
}

序列化器

public class Serializer {

    public static byte[] serialize(Object o) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new SurrogateOutputStream(baos); // Magically handle Pojos !
        oos.writeObject(o);
        oos.flush();
        oos.close();
        return baos.toByteArray();
    }

    public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        Object o = ois.readObject();
        bais.close();
        return o;
    }
}

主要(测试)

public static void main(String[] args) throws Exception {
    Area area = new Area(new Rectangle(0, 0, 100, 100)); // The original object, NOT SERIALIZABLE !
    System.out.println(area.contains(new Rectangle(1, 1, 10, 10))); // Good as new !
    System.out.print("serializing...");
    byte[] pojoBytes = Serializer.serialize(area); // Serialize
    System.out.println("done");
    System.out.print("deserializing...");
    area = (Area) Serializer.deserialize(pojoBytes); // Deserialize
    System.out.println("done");
    System.out.println(area.contains(new Rectangle(1, 1, 10, 10))); // Good as new !
}

main() 中,我从一个 矩形 创建一个 Area,该区域从坐标 (0,0) 开始,宽度为 100, 100高。然后我测试 (1,1) 中宽度为 10、高度为 10 的矩形是否位于该区域内(强制位于该区域内)。序列化和反序列化后,我测试相同的矩形是否仍在新的 Area 内。

这可能还不够,因为新的 Area 对象是从 Rectangle 创建的(请参阅 AreaSurrogate)。所以这可能不适用于其他区域形状..

预期输出

true
serializing...done
deserializing...done
true

关于Java 序列化对象(如区域),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21921777/

相关文章:

python - 如何用python获取选择区域坐标?

java - 方法未正确打印 ArrayList 内容

java - 如何在 Firebase RecyclerView 中添加加载进度条

java - 无法将值插入数据库

python - 序列化 ctype 联合

html - 图像映射标签在 Chrome 和 Firefox 中不起作用

java - Spring Data JPA - 使用标志列的存储库 findAll 方法

c# - 为值对象序列化自定义 NewtonSoft.Json

c# - 将 XML 反序列化为 C# 类

matlab - 如何在matlab中通过三角测量3D物体来计算面积?