繁体   English   中英

Java像区域一样序列化对象

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM