为什么在Serializable类中使用Thread引用很好但是初始化它会导致NotSerializableException

时间:2018-03-05 21:57:01

标签: java serialization

class A implements Serializable{

    int a;
    Thread th;
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public Thread getTh() {
        return th;
    }
    public void setTh(Thread th) {
        this.th = th;
    }

}


public class Test {

    public static void main(String[] args) {

        A a = new A();
        a.setA(10);
        //a.setTh(new Thread());
        try {
            ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(new File("G:\\Sample1.db")));
            oos1.writeObject(a);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            ObjectInputStream ois1 = new ObjectInputStream(new FileInputStream(new File("G:\\Sample1.db")));
            A a1 = (A)ois1.readObject();
            System.out.println(a1.getA()+" "+a.getTh());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

上面的代码将正常运行但是如果我取消注释a.setTh(new Thread());它抛出NotSerializableException。 由于Thread不是Serializable,为什么默认的序列化过程不会在它自身之前抱怨“th”变量。

2 个答案:

答案 0 :(得分:3)

Thread本身没有实现Serializable,但这里是Thread的子类,它执行:

class SerializableThread extends Thread implements Serializable {
  @Override public void run() {}
}

SerializableThread现在是SerializableThread,因此可以序列化它的实例。

编译器不知道您是否会在引用中存储不可序列化的Thread或可序列化的Thread(或null,这也是可序列化的),因此它不会停止向实现Thread的类添加Serializable字段。

如果您想确保只设置可序列化的Thread,则可以更改setter方法的类型,例如:

public void setTh(SerializableThread th) {

public <T extends Thread & Serializable> void setTh(T th) {

但是,值得注意的是,这并不能完全保证th的可序列化,因为它可以传递地包含对非可序列化实例的引用。这只是Java序列化机制的局限之一。

答案 1 :(得分:2)

作为一个类的线程是不可序列化的,出于很多非常实际的原因,但理论上,可能会从Thread派生出一个可序列化的类。

我建议你制作一个transient因为反序列化一个Thread实例没有意义。