Java &引用;“没有有效的构造函数”;序列化Path2D.Double的子类时

Java &引用;“没有有效的构造函数”;序列化Path2D.Double的子类时,java,serialization,subclass,deserialization,Java,Serialization,Subclass,Deserialization,我正在尝试序列化Path2D.Double的子类,序列化可以工作,但反序列化无法工作,因为出现以下异常: Exception in thread "main" java.io.InvalidClassException: CustomShape; no valid constructor at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:147) at java.i

我正在尝试序列化Path2D.Double的子类,序列化可以工作,但反序列化无法工作,因为出现以下异常:

Exception in thread "main" java.io.InvalidClassException: CustomShape; no valid constructor
at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:147)
at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:755)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at CustomShape.main(CustomShape.java:38)
这可能是由于超类Path2D未实现可序列化吗?但是,Path2D.Double本身也无法反序列化

这是我的密码:

import java.awt.geom.Path2D;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class CustomShape extends Path2D.Double {
    private static final long serialVersionUID = 1L;

    public CustomShape() {
        super();
    }

    public static void main(String[] args) throws Exception {
        //Make Shape
        //Path2D shape = new Path2D.Double(); //works
        Path2D shape = new CustomShape(); //doesn't work 
        shape.moveTo(0, 0);
        shape.lineTo(0, 10);
        shape.lineTo(10, 10);
        shape.lineTo(10, 0);
        shape.closePath();

        File file = new File(System.getProperty("user.dir"), "shape");
        //Save Shape
        if (!file.exists()) {
            file.createNewFile();
        }
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
        out.writeObject(shape);
        out.flush();
        out.close();

        //Load Shape
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
        Object obj = in.readObject();
        in.close();

        System.out.println(obj);
    }
}

上周我遇到了同样的问题,今天终于找到了答案。Path2D对象将其构造函数声明为包私有。由于java序列化要求第一个不可序列化的父类具有无参数构造函数,并且不可访问,因此任何不在Path2D自身包中的Path2D扩展都不会反序列化。老实说,我认为这对Java来说是一个错误,因为所有其他使用Float/Double子类的AWT抽象形状都声明它们的默认构造函数是受保护的


如果您好奇的话,我通过
java.io.ObjectStreamClass.getSerializableConstructor(Class)
跟踪找到了根本原因。您会发现,当它找到一个不可访问的构造函数时,它返回null。

我上周遇到了同样的问题,今天终于找到了答案。Path2D对象将其构造函数声明为包私有。由于java序列化要求第一个不可序列化的父类具有无参数构造函数,并且不可访问,因此任何不在Path2D自身包中的Path2D扩展都不会反序列化。老实说,我认为这对Java来说是一个错误,因为所有其他使用Float/Double子类的AWT抽象形状都声明它们的默认构造函数是受保护的


如果您好奇的话,我通过
java.io.ObjectStreamClass.getSerializableConstructor(Class)
跟踪找到了根本原因。当它找到一个不可访问的构造函数时,您会发现它返回null。

显示Path2D及其内部类Double的声明。@Marko Topolnik它们是jre类
java.awt.geom.Path2D
具有
private
readObject
writeObject
实现。它似乎在处理包private
transient double[]doublechord
对不起,没有看到导入。我正在查看代码,但看不到问题的原因。您不需要file.exists()/file.createNewFile()代码。新建FileOutputStream()就足够了。显示Path2D及其内部类Double的声明。@Marko Topolnik它们是jre类
java.awt.geom.Path2D
具有
private
readObject
writeObject
实现。它似乎在处理包private
transient double[]doublechord
对不起,没有看到导入。我正在查看代码,但看不到问题的原因。您不需要file.exists()/file.createNewFile()代码。新建FileOutputStream()就足够了。