我的Java项目中有数千个类.其中一些实现了可序列化的接口.现在这是一个问题.可能有人可以上课,添加既不是临时的也不是可序列化的新变量.代码可以正常编译,但是进程会在运行时崩溃.
为了说明这一点
class Foo implements Serializable { .... // all good }
class Foo implements Serializable
{
// OOps, executorService is not serializable. It's not declared as transient either
private ExecutorService executorService = ..
}
我正在考虑编写将通过所有类并确保“真正的可序列化”的单元测试.我已经阅读了一些有关序列化特定对象的讨论.我了解该过程,但这需要
1)创建一个对象.
2)序列化然后
3)反序列化.
有没有更有效,更实用的方法.也许要使用反射.遍历所有类,如果类具有可序列化的属性,则所有属性必须可序列化或具有transient关键字.
有什么想法吗?
最佳答案
1) creating an object. 2) serializing and then 3) deserializing.
此列表不完整;您还需要初始化.考虑示例:
class CanBeSerialized implements Serializable {
private String a; // serializable
private Thread t; // not serializable
}
class CannotBeSerialized implements Serializable {
private String a; // serializable
private Thread t = new Thread(); // not serializable
}
您可以序列化和反序列化第一个,但第二个将获得NotSerializableException.更复杂的是,如果使用接口,您将永远无法判断类是否将通过序列化,因为将流传输的是该接口背后的类的具体对象:
class PerhapsCanBeSerializedButYouNeverKnow implements Serializable {
private Runnable r; // interface type - who knows?
}
前提是您可以保证所有类和要测试的类所使用的类都满足以下条件:
>默认构造函数存在,
>字段中没有接口类型,
那么您可以通过反射自动创建和初始化它们,然后测试序列化.但这是一个非常困难的条件,不是吗?否则,正确的初始化将取决于手动工作.
您可以通过其他方式使用反射:遍历要检查的Class对象的列表,获取它们的Field [],并验证它们是否是瞬时的(Field.getModifiers())或它们是否直接实现Serializable( Field.getType().getInterfaces())或间接(通过超级接口或类).另外,请考虑要检查的深度,具体取决于序列化机制的工作深度.
正如Ryan正确指出的那样,如果代码足够邪恶,则此静态序列化检查将失败:
class SeeminglySerializable implements Serializable {
// ...
private void writeObject/readObject() {
throw new NotSerializableException();
}
}
或readObject()/ writeObject()实现不好.要针对此类问题进行测试,您需要实际测试序列化过程,而不是其背后的代码.