如何在Java中testing一个类正确地实现了Serializable(不仅仅是一个Serializable的实例)

我正在实现一个类是可序列化的(所以它是一个价值对象使用w / RMI)。 但是我需要testing它。 有没有办法很容易做到这一点?

澄清 :我正在实现这个类,所以在类定义中使用Serializable是很简单的。 我需要手动序列化/反序列化,看看它是否工作。

我发现这个C#的问题 ,有没有类似的Java答案?

简单的方法是检查对象是java.io.Serializable还是java.io.Externalizable的实例,但这并不能真正certificate对象是可序列化的。

唯一可以肯定的就是尝试一下。 最简单的testing是这样的:

 new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(myObject); 

并检查它不会抛出exception。

Apache Commons Lang提供了一个相当简单的版本:

 SerializationUtils.serialize(myObject); 

再次检查exception。

你仍然可以更加严格,并检查它是否反序列化为原来的东西:

 Serializable original = ... Serializable copy = SerializationUtils.clone(original); assertEquals(original, copy); 

等等。

基于skaffman的回答的效用方法:

 private static <T extends Serializable> byte[] pickle(T obj) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); oos.close(); return baos.toByteArray(); } private static <T extends Serializable> T unpickle(byte[] b, Class<T> cl) throws IOException, ClassNotFoundException { ByteArrayInputStream bais = new ByteArrayInputStream(b); ObjectInputStream ois = new ObjectInputStream(bais); Object o = ois.readObject(); return cl.cast(o); } 

这个代码应该这样做…

 import java.io.ByteArrayOutputStream; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; public class Main { public static void main(String[] args) { System.out.println(isSerializable("Hello")); System.out.println(isSerializable(new Main())); } public static boolean isSerializable(final Object o) { final boolean retVal; if(implementsInterface(o)) { retVal = attemptToSerialize(o); } else { retVal = false; } return (retVal); } private static boolean implementsInterface(final Object o) { final boolean retVal; retVal = ((o instanceof Serializable) || (o instanceof Externalizable)); return (retVal); } private static boolean attemptToSerialize(final Object o) { final OutputStream sink; ObjectOutputStream stream; stream = null; try { sink = new ByteArrayOutputStream(); stream = new ObjectOutputStream(sink); stream.writeObject(o); // could also re-serilalize at this point too } catch(final IOException ex) { return (false); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { // should not be able to happen } } } return (true); } } 

简而言之,您可以想出一些候选对象,并尝试使用您select的机制来序列化它们。 这里的testing是在编组/解组过程中不会遇到任何错误,并且生成的“再水合”对象与原始对象相同。

另外,如果你没有任何候选对象,你可以实现一个基于reflection的testing来反省你的类的(非静态的,非暂态的)字段,以确保它们也是可序列化的。 从经验上讲,这个令人惊讶的复杂得惊人的迅速,但它可以做到一个合理的程度。

后一种方法的缺点是,如果一个字段是例如List<String> ,那么你可能因为没有一个严格的可序列化字段而导致该类失败,或者简单地假定将使用List的可序列化实现。 两者都不是完美的。 (注意,后面的问题也存在于示例中;如果testing中使用的每个示例都使用可序列化的列表,则实际上没有什么能够阻止其他代码使用不可序列化的版本)。

你可以做以下testing:

  • 序列化对象到文件并确保没有抛出exception。
  • 另外,将对象反序列化并与原始对象进行比较。

下面是序列化和反序列化对象到文件的示例:

http://www.rgagnon.com/javadetails/java-0075.html

http://www.javapractices.com/topic/TopicAction.do?Id=57

这只适用于完全填充的对象,如果您要求在顶级对象中构成的任何对象也是可序列化的,那么它们不能为null,因为这个testing是有效的,因为序列化/反序列化跳过空对象