JVM (Java virtual machine), their internal state can only be maintained in memory. Once When the JVM stops working, the internal state disappears, so it is non-persistent.
Persistence), the usual approach is to save it to a file or database.
serialize. Through serialization, you can easily serialize it in the JVM. The active object is converted into a byte array (stream) for storage.
class Person implements Serializable { private String name; private int age; public Person(String name ,int age){ this.name = name; this.age =age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "name is " + name + " , age is " + age; } }public class Test { private final static String TEMPFILE = "E:" + File.separator + "test.txt"; public static void main(String[] args) { Person person = new Person("test",100); write(person); // 关键 -> 序列化之后重新对对象进行赋值 person = new Person("hello",999); read(person); // 输出结果: // name is test , age is 100,序列化成功 // 反序列化成功,name is test , age is 100 } // 通过 ObjectOutputStream 进行对象的序列化操作 private static void write(Person person) { try { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(TEMPFILE)); oos.writeObject(person); oos.close(); System.out.println(person+",序列化成功"); } catch (Exception e) { e.printStackTrace(); } } // 通过 ObjectInputStream 进行对象的反序列化操作 private static void read(Person person) { try { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(TEMPFILE)); person = (Person) ois.readObject(); ois.close(); System.out.println("反序列化成功.,"+person); } catch (Exception e) { e.printStackTrace(); } } }Observe the output results. We reassign the value after the object is serialized, and the result of deserialization is still the same as the value before the object was serialized. Consistent, this also indirectly proves that the object is permanently stored and persistence is achieved.
is not unserializable).
// 序列化过程、调用过程与上述例子一致,省略代码... // 这里只对内部类 Person 的 age 属性进行修改class Person implements Serializable { // 用 transient 修该变量 private transient int age; // 省略部分代码...} // 调用后的输出结果: // name is test , age is 100,序列化成功 // 反序列化成功.,name is test , age is 0Observe the output results and find that the age before serialization is 100, while the age read through deserialization is 0. The initial value of the parameter of type int is 0, which means that the parameter has not been serialized.
It is not that they cannot be serialized).
// 序列化过程、调用过程与上述例子一致,省略代码... // 这里只对内部类 Person 的 name 属性进行修改class Person implements Serializable { // 用 static 修该变量 private static String name; // 省略部分代码...} // 输出结果: // name is test , age is 100,序列化成功//反序列化成功.,name is hello , age is 100Observe the output results and find that the value of name is hello, not test before serialization. The different values before and after indicate that it has not been serialized. And because the characteristics of static are related to classes, the variable was reassigned after the serialization operation, resulting in its value not being null, but hello.
cannot be serialized.
// 序列化过程、调用过程与上述例子一致,省略代码... // 这里只对内部类 Person 的 name 属性进行修改class Person implements Serializable { //新增成员变量 private Thread myThread = new Thread(); //省略部分代码...} // 输出结果(抛出异常): // Caused by: java.io.NotSerializableException: java.lang.Thread
// 序列化操作代码与上面一致... // 这里只对内部类 Person 的属性进行修改。class Person implements Serializable { private static String name; private transient int age; // 自定义序列化操作 private void writeObject(ObjectOutputStream out) throws IOException{ out.defaultWriteObject(); out.writeObject(name); out.writeInt(age); } // 自定义反序列化操作 private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException{ in.defaultReadObject(); name = (String) in.readObject(); age = in.readInt(); } // 省略部分代码...} // 输出结果: // name is test , age is 100,序列化成功 // 反序列化成功,name is test , age is 100
writeExternal and readExternal methods for custom serialization and deserialization ization process.
parameterless constructor.
// 序列化操作代码与上面一致,这里只对内部类 Person 的进行修改。 class Person implements Externalizable { private static String name; private transient int age; // 重点 ->必须有无参构造函数 public Person(){ } public Person(String name ,int age){ this.name = name; this.age =age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "name is " + name + " , age is " + age; } // 实现接口的方法 @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name); out.writeInt(age); } // 实现接口的方法 @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = (String) in.readObject(); age = in.readInt(); } } // 输出结果: // name is test , age is 100,序列化成功 // 反序列化成功,name is test , age is 100
method is modified, the serialVersionUID ** remains unchanged **.
properties are modified, the regenerated serialVersionUID** will change**.
因此说明序列化是作用于对象属性上的。
下面通过实例来探究下 serialVersionUID 的具体作用:
首先我们对对象进行序列化操作(这里取消了反序列化的操作)
// 序列化操作代码与上面例子一致...// 这里取消了反序列化的操作public static void main(String[] args) { Person person = new Person("test",100); write(person); person = new Person("java", 200); //read(person);}
然后新增一个对象的属性,再进行反序列化操作
// 省略部分代码,与上面的代码一致...class Person implements Serializable { private String name; private age; //新增成员变量 private int phone; //省略部分代码... } }public static void main(String[] args) { Person person = new Person("test",100); //write(person); person = new Person("java", 200); read(person); }// 输出结果(抛出异常):// java.io.InvalidClassException: Person;
观察代码,在序列化对象并没有添加 serialVersionUID 的情况,在对象序列化之后如果改变了对象的属性,反序列化就会抛出异常。如果对象添加了 serialVersionUID 就不会出现这种情况,这里就不验证了。
以上就是13.Java 基础 - 序列化的内容,更多相关内容请关注PHP中文网(www.php.cn)!