Java 反序列化时发生异常

Java 反序列化时发生异常,java,exception,serialization,deserialization,Java,Exception,Serialization,Deserialization,我试图反序列化一个实现可序列化接口的类,并扩展不可序列化的类 /** * */ package com.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutp

我试图反序列化一个实现可序列化接口的类,并扩展不可序列化的类

/**
* 
*/
package com.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class SerializationTest  implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = -1324438308227634614L;

class Papa{
    Papa(){
        System.out.println("Papa called..");
    }
}
class Student extends Papa implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 8667392485783922740L;

    String name;
    int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 
     */
    public Student() {
        System.out.println("Constructor called");
    }

}

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
    Student arvind = new SerializationTest().new Student();
    arvind.setName("Arvind");
    arvind.setId(123);

    serialize(arvind);
    System.out.println("Serialization done..");
    deserialize();
}

/**
 * @throws IOException 
 * @throws FileNotFoundException 
 * @throws ClassNotFoundException 
 * 
 */
private static void deserialize() throws FileNotFoundException, IOException, ClassNotFoundException {

    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("tests.txt"));

    Student arvind = (Student)ois.readObject();
    System.out.println("Deserialize name - " + arvind.getName());
    System.out.println(arvind.getId());
    ois.close();

}

/**
 * @param arvind
 * @throws IOException
 * @throws FileNotFoundException
 */
private static void serialize(Student arvind) throws IOException, FileNotFoundException {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("tests.txt"));

    oos.writeObject(arvind);
    oos.flush();
    oos.close();
}
}
我得到以下例外情况-

Exception in thread "main" java.io.InvalidClassException: com.test.SerializationTest$Student; no valid constructor
at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(Unknown Source)
at java.io.ObjectStreamClass.checkDeserialize(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.test.SerializationTest.desseialize(SerializationTest.java:88)
at com.test.SerializationTest.main(SerializationTest.java:75)
我按照的答案创建了默认构造函数,但它也没有帮助


非常感谢您的建议和帮助。

您还需要使父类可序列化

因此,您的代码将是:

class Papa implements Serializable {
         Papa(){
            System.out.println("Papa called..");
        }
}
还记得吗

可序列化类应具有可访问(公共或受保护)的无参数构造函数,以便序列化反射机制可以创建该类的实例

有关更多详细信息,请参阅:

在反序列化过程中,不可序列化类的字段将 使用的public或protected no arg构造函数初始化 班级。不带参数的构造函数必须可被指定的子类访问 可序列化。可序列化子类的字段将被还原 从小溪里


您所需要的只是将Student和Papa公共类都放在单独的文件中,或者像这样使它们都是静态的

static class Papa{
    Papa(){
        System.out.println("Papa called..");
    }
}
static class Student extends Papa implements Serializable{

    /**
     *
     */
    private static final long serialVersionUID = 8667392485783922740L;

    String name;
    int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     */
    public Student() {
        System.out.println("Constructor called");
    }

}

代码不起作用的原因是内部Papa类的构造函数不能在Student类的构造函数中直接调用。我们已经将Papa设置为静态,以摆脱这种束缚。

请将类设置为
Papa
Student
静态内部类。现在它们是常见的内部类,如果不创建
SerializationTest
的实例,就无法创建它们的实例。感谢Ivan的快速响应。是的,当两个类都被标记为static或者只有
Papa
类被标记为static时,它才起作用,但是我想了解使父类
Papa
静态的背后的逻辑是什么?为什么它不能非静态工作?谢谢Eugen的回复!!是的,当两个类都被标记为static或者只有Papa类被标记为static时,它是有效的,但是我想了解使父类Papa为static背后的逻辑是什么?为什么它不以非静态方式工作?太好了!!关键是。。。现在有道理了。。谢谢@Eugen