public class SerializationUtils { public static ByteArrayOutputStream serialize(Object object) throws IOException { System.out.print("Serializing: " + object); ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bout); out.writeObject(object); out.close(); return bout; } public static void deserialize(ByteArrayOutputStream bout) throws IOException, ClassNotFoundException { ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); ObjectInputStream in = new ObjectInputStream(bin); Object readObject = in.readObject(); System.out.println(", deserialized: " + readObject); } }
Junit:
public class MySerializableClass implements Serializable { } public class MySerializationTest { private String myJunitStringField = "hello"; static class MyStaticNestedSerializableClass implements Serializable { public int getLength(String s) { // Error: java: non-static variable this cannot be referenced from a static context //System.out.println(MySerializationTest.this);// static nested class does not have reference to outer class return s.length(); } } interface MySerializableFunction<T, R> extends Function<T, R>, Serializable {} @Test public void testSerialization() throws IOException, ClassNotFoundException { deserialize(serialize(1)); // Serializing: 1, deserialized: 1 deserialize(serialize("aaa")); // Serializing: aaa, deserialized: aaa deserialize(serialize(new MySerializableClass())); // Serializing: com.bawi.serialization.MySerializableClass@4520ebad, deserialized: com.bawi.serialization.MySerializableClass@4f933fd1 deserialize(serialize(new MyStaticNestedSerializableClass())); // Serializing: com.bawi.serialization.MySerializationTest$MyStaticNestedSerializableClass@4520ebad, deserialized: com.bawi.serialization.MySerializationTest$MyStaticNestedSerializableClass@4f933fd1 deserialize(serialize((MySerializableFunction<String, Integer>) s -> s.length())); } static class MyStaticNestedNonSerializableClass {} // missing implements Serializable class MyInnerSerializableClass implements Serializable { public int getLength(String s) { System.out.println("myJunitStringField=" + myJunitStringField); // direct access to private outer class fields System.out.println(MySerializationTest.this); // reference to enclosing instance of the outer class return s.length(); } } @Test//(expected = java.io.NotSerializableException.class) public void failWithNotSerializableException() throws IOException, ClassNotFoundException { // NotSerializableException: com.bawi.serialization.MySerializationTest$MyStaticNestedNonSerializableClass // deserialize(serialize(new MyStaticNestedNonSerializableClass())); // inner (non static nested) class has reference to non-serializable outer class (junit com.bawi.serialization.MySerializationTest) MyInnerSerializableClass myInnerSerializableClass = new MyInnerSerializableClass(); myInnerSerializableClass.getLength("a"); // myJunitStringField=hello // com.bawi.serialization.MySerializationTest@1324409e // java.io.NotSerializableException: com.bawi.serialization.MySerializationTest // deserialize(serialize(myInnerSerializableClass)); class MyLocalSerializableClass implements Serializable { @Override public String toString() { return MySerializationTest.this + ""; } } // java.io.NotSerializableException: com.bawi.serialization.MySerializationTest // deserialize(serialize(new MyLocalSerializableClass())); //anonymous is inner class: java.io.NotSerializableException: com.bawi.serialization.MySerializationTest // deserialize(serialize(new Serializable(){ // @Override // public String toString() { // return MySerializationTest.this + ""; // } // })); // like local classes, anonymous classes have access to local variables of enclosing scope that are effectively final // anonymous class definition (within {}) is an expression and must be part of the statement and end with semicolon MyStaticNestedSerializableClass myAnonymousInnerSerializableClass = new MyStaticNestedSerializableClass() { @Override public int getLength(String s) { System.out.println("myJunitStringField=" + myJunitStringField); // direct access to private outer class fields System.out.println(MySerializationTest.this); return s.length() + 2; } }; myAnonymousInnerSerializableClass.getLength("aa"); // java.io.NotSerializableException: com.bawi.serialization.MySerializationTest // deserialize(serialize(myAnonymousInnerSerializableClass)); //java.io.NotSerializableException: com.bawi.serialization.MySerializationTest$$Lambda$1/1576861390 // deserialize(serialize((Function<String, Integer>) s -> s.length())); } }
If we make MySerializationTest implements Serializable
then we will not get java.io.NotSerializableException: com.bawi.serialization.MySerializationTest