001package intermediate; 002 003import com.sandwich.koan.Koan; 004 005import java.io.*; 006import java.util.logging.Logger; 007 008import static com.sandwich.koan.constant.KoanConstants.__; 009import static com.sandwich.util.Assert.assertEquals; 010 011 012public class AboutSerialization { 013 014 @Koan 015 public void simpleSerialization() throws FileNotFoundException, IOException, ClassNotFoundException { 016 String s = "Hello world"; 017 // serialize 018 File file = new File("SerializeFile"); 019 file.deleteOnExit(); 020 ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); 021 os.writeObject(s); 022 os.close(); 023 024 // deserialize 025 ObjectInputStream is = null; 026 try { 027 is = new ObjectInputStream(new FileInputStream("SerializeFile")); 028 String otherString = (String) is.readObject(); 029 assertEquals(otherString, __); 030 } finally { 031 closeStream(is); 032 } 033 } 034 035 static class Starship implements Serializable { 036 037 // Although it is not enforced, you should define this constant 038 // to make sure you serialize/deserialize only compatible versions 039 // of your objects 040 private static final long serialVersionUID = 1L; 041 int maxWarpSpeed; 042 } 043 044 @Koan 045 public void customObjectSerialization() throws IOException, ClassNotFoundException { 046 Starship s = new Starship(); 047 s.maxWarpSpeed = 9; 048 File file = new File("SerializeFile"); 049 file.deleteOnExit(); 050 ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); 051 os.writeObject(s); 052 os.close(); 053 054 ObjectInputStream is = null; 055 try { 056 is = new ObjectInputStream(new FileInputStream("SerializeFile")); 057 Starship onTheOtherSide = (Starship) is.readObject(); 058 assertEquals(onTheOtherSide.maxWarpSpeed, __); 059 } finally { 060 closeStream(is); 061 } 062 } 063 064 static class Engine { 065 String type; 066 067 public Engine(String t) { 068 type = t; 069 } 070 } 071 072 @SuppressWarnings("serial") 073 static class Car implements Serializable { 074 // Transient means: Ignore field for serialization 075 transient Engine engine; 076 077 // Notice these methods are private and will be called by the JVM 078 // internally - as if they where defined by the Serializable interface 079 // but they aren't defined as part of the interface 080 private void writeObject(ObjectOutputStream os) throws IOException { 081 os.defaultWriteObject(); 082 os.writeObject(engine.type); 083 } 084 085 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { 086 is.defaultReadObject(); 087 engine = new Engine((String) is.readObject()); 088 } 089 } 090 091 @Koan 092 public void customObjectSerializationWithTransientFields() throws FileNotFoundException, IOException, ClassNotFoundException { 093 // Note that this kind of access of fields is not good OO practice. 094 // But let's focus on serialization here :) 095 Car car = new Car(); 096 car.engine = new Engine("diesel"); 097 File file = new File("SerializeFile"); 098 file.deleteOnExit(); 099 ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); 100 os.writeObject(car); 101 os.close(); 102 103 ObjectInputStream is = null; 104 try { 105 is = new ObjectInputStream(new FileInputStream("SerializeFile")); 106 Car deserializedCar = (Car) is.readObject(); 107 assertEquals(deserializedCar.engine.type, __); 108 } finally { 109 closeStream(is); 110 } 111 } 112 113 @SuppressWarnings("serial") 114 class Boat implements Serializable { 115 Engine engine; 116 } 117 118 @Koan 119 public void customSerializationWithUnserializableFields() throws FileNotFoundException, IOException { 120 Boat boat = new Boat(); 121 boat.engine = new Engine("diesel"); 122 File file = new File("SerializeFile"); 123 file.deleteOnExit(); 124 ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); 125 String marker = "Start "; 126 try { 127 os.writeObject(boat); 128 } catch (NotSerializableException e) { 129 marker += "Exception"; 130 } 131 os.close(); 132 assertEquals(marker, __); 133 } 134 135 @SuppressWarnings("serial") 136 static class Animal implements Serializable { 137 String name; 138 139 public Animal(String s) { 140 name = s; 141 } 142 } 143 144 @SuppressWarnings("serial") 145 static class Dog extends Animal { 146 public Dog(String s) { 147 super(s); 148 } 149 } 150 151 @Koan 152 public void serializeWithInheritance() throws IOException, ClassNotFoundException { 153 Dog d = new Dog("snoopy"); 154 File file = new File("SerializeFile"); 155 file.deleteOnExit(); 156 ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file)); 157 os.writeObject(d); 158 os.close(); 159 160 ObjectInputStream is = null; 161 try { 162 is = new ObjectInputStream(new FileInputStream("SerializeFile")); 163 Dog otherDog = (Dog) is.readObject(); 164 assertEquals(otherDog.name, __); 165 } finally { 166 closeStream(is); 167 } 168 } 169 170 static class Plane { 171 String name; 172 173 public Plane(String s) { 174 name = s; 175 } 176 177 public Plane() { 178 } 179 180 } 181 182 @SuppressWarnings("serial") 183 static class MilitaryPlane extends Plane implements Serializable { 184 public MilitaryPlane(String s) { 185 super(s); 186 } 187 } 188 189 @Koan 190 public void serializeWithInheritanceWhenParentNotSerializable() throws FileNotFoundException, IOException, ClassNotFoundException { 191 MilitaryPlane p = new MilitaryPlane("F22"); 192 193 ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("SerializeFile")); 194 os.writeObject(p); 195 os.close(); 196 197 ObjectInputStream is = null; 198 try { 199 is = new ObjectInputStream(new FileInputStream("SerializeFile")); 200 MilitaryPlane otherPlane = (MilitaryPlane) is.readObject(); 201 // Does this surprise you? 202 assertEquals(otherPlane.name, __); 203 204 // Think about how serialization creates objects... 205 // It does not use constructors! But if a parent object is not serializable 206 // it actually uses constructors and if the fields are not in a serializable class... 207 // unexpected things - like this - may happen 208 } finally { 209 closeStream(is); 210 } 211 } 212 213 private void closeStream(ObjectInputStream ois) { 214 if (ois != null) { 215 try { 216 ois.close(); 217 } catch (IOException x) { 218 Logger.getAnonymousLogger().severe("Unable to close reader."); 219 } 220 } 221 } 222 223} 224