シリアル化を導入する前に、まず次の概念を理解する必要があります:
非永続性: JVM (Java 仮想マシン) を持つオブジェクトの場合、その内部状態は次のとおりです。 JVM が動作を停止すると、内部状態は失われるため、非永続的です。
)、通常のアプローチは、オブジェクトを ファイルまたはデータベース に保存することです。
逆シリアル化: ファイルまたはデータベース内のバイト配列 (ストリーム) を JVM アクティブ オブジェクトに変換します。
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(); } } }
1.transient
// 序列化过程、调用过程与上述例子一致,省略代码... // 这里只对内部类 Person 的 age 属性进行修改class Person implements Serializable { // 用 transient 修该变量 private transient int age; // 省略部分代码...} // 调用后的输出结果: // name is test , age is 100,序列化成功 // 反序列化成功.,name is test , age is 0
// 序列化过程、调用过程与上述例子一致,省略代码... // 这里只对内部类 Person 的 name 属性进行修改class Person implements Serializable { // 用 static 修该变量 private static String name; // 省略部分代码...} // 输出结果: // name is test , age is 100,序列化成功//反序列化成功.,name is hello , age is 100
// 序列化过程、调用过程与上述例子一致,省略代码... // 这里只对内部类 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
では、クラスに
同時に、そのシリアル化プロセスはパブリックメソッドで定義されているため、安全ではありません。
// 序列化操作代码与上面一致,这里只对内部类 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
オブジェクトの
因此说明序列化是作用于对象属性上的。
下面通过实例来探究下 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)!