3

这是我的小班:

import java.io.Serializable;
public abstract class SerializableCallback extends Callback
implements Serializable {
    private static final long serialVersionUID = 4544768712188843966L;
    public abstract void handleMessage(Message msg);
}

这是它更小的父级Callback

public abstract class Callback {
    public abstract void handleMessage(Message msg);
}

这是我的测试:

public void testSerialization() throws IOException, ClassNotFoundException {
    SerializableCallback c = new SerializableCallback() {
        private static final long serialVersionUID = -4852385037064234702L;
        @Override
        public void handleMessage(Message msg) {
            callbackMethod();
        }
    };

    FileOutputStream fos = new FileOutputStream(FILE);
    ObjectOutputStream out = new ObjectOutputStream(fos);
    out.writeObject(c); // fails
    out.close();

    FileInputStream fis = new FileInputStream(FILE);
    ObjectInputStream in = new ObjectInputStream(fis);
    Object object = in.readObject();
    @SuppressWarnings("unused")
    SerializableCallback d = (SerializableCallback) object;
}

private void callbackMethod() {}

测试NotSerializableException在注释指示的行上给了我一个。这里有几件事肯定不能引起:

  1. 缺少可序列化声明
  2. 不可序列化的字段:根本没有字段
  3. 最接近的不可序列化父类型的不可见非参数构造函数

那么导致异常的原因是什么

4

3 回答 3

6

您的类没有无参数构造函数。它有一个构造函数,它接受一个this外部类的参数。如果你做了 testSerialization()static它可能会解决问题。

但我怀疑你直接的真正问题是你的嵌套类引用了外部类,而外部类不是可序列化的。

于 2012-10-16T14:58:12.443 回答
2

只是为了进一步解决您对彼得答案的评论(评论太长),SerializableCallback您的测试方法中的匿名类在技术上是一个内部类

  • 当在非静态方法中声明时,匿名类本质上是非静态内部类。
  • 当在静态方法中声明时,匿名类本质上是静态内部类。

这就是为什么切换到static工作。由于它使您创建的匿名类成为静态类,因此它不再包含对您的测试类的隐式引用,因此它是可序列化的。

请记住,在非静态级别声明的匿名类和内部类始终包含对封闭类的引用。如果没有,您将无法调用callbackMethod()匿名类,因为匿名类没有声明它。

ObjectOutputStream试图序列化你的匿名SerializableCallback时,它试图序列化回调测试类,因为它SerializableCallback持有对它的引用。这就像试图序列化这个类:

// Declared in its own file
public class MySerializableCallback extends SerializableCallback {
    private static final long serialVersionUID = -4852385037064234702L;

    // Equiv to Callback.this in an inner class
    private final CallbackTest test;

    public MySerializableCallback(CallbackTest test) {
        this.test = test;
    }

    @Override
    public void handleMessage(Message msg) {
        test.callbackMethod();
    }
}

如果你试图序列化这个类,很明显它会失败,因为它CallbackTest可能是不可序列化的。

于 2012-10-16T15:46:01.790 回答
1

检查这些情况

在这些情况下,序列化失败:

  • 删除实例变量。

  • 更改实例变量的类型。

  • 将实例变量从非瞬态更改为瞬态。

  • 将实例变量从非静态更改为静态。

  • 在层次结构中上下移动类。

于 2012-10-16T14:59:43.170 回答