我已经阅读了一些有关 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/