[英]Java Serializing Objects Like an Area
我已经读了一些有关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);
}
}
这取决于是否要在另一程序或另一种语言中使用该Object
,那么可以使用 JSON(或XML)。
但是,如果您想在另一个JAVA程序中重用该Object
,那么我想寻找一种方法使非可序列化的Objects
序列化会更方便。
我尚未对其进行测试,但是在此博客中找到了一个有前途的解决方案(抱歉,它是法文) 。 我会尽力总结一下:
你有什么
说您有一个名为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
的成员变量并将其替换 。
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
,因此您可能必须测试反序列化后您的区域是否仍然具有相同的特性)
AreaSurrogate
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);
}
}
SurrogateOutputStream
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()
我从Rectangle
开始创建一个Area
,该Area
以坐标(0,0)开始,宽100高100。 然后,我测试宽度(10)和高度(10)的(1,1)中的Rectangle是否在区域内(强制)。 序列化和反序列化后,我测试,如果同样的矩形仍是新的内部Area
。
这可能是不够的,因为新的Area
Object是从Rectangle
创建的(请参见AreaSurrogate
)。 因此这可能不适用于其他Area形状。
预期产量
true
serializing...done
deserializing...done
true
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.