Java 직렬화는 Java Object
객체를 이진 바이트 시퀀스 byte[]
Java Object
变为一个二进制字节序列byte[]
Java反序列化就是把一个二进制字节序列byte[]
变为Java对象Java Object
字节输出流对象,将对象的输出流写到文件中(结合FileOutputStream使用)
实例:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt")); 或 FileOutputStream fout = new FileOutputStream("1.txt"); ObjectOutputStream out = new ObjectOutputStream(fout);
此外ObjectOutputStream还提供了writeObject()
方法来序列化一个对象,并将它发送到输出流。
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt")); out.writeObject(new Test("Sentiment",10)); //对Test类中的构造方法进行传参
字节输入流对象,将文件中的二进制字节序列进行反序列化操作(结合FileInputStream)
实例:
ObjectInputStream in = new ObjectInputStream(new FileInputStream("1.txt")); 或 FileInputStream fin = new FileInputStream("1.txt"); ObjectInputStream oin = new ObjectInputStream(fin);
此外ObjectInputStream还提供readObject()
方法从流中取出下一个对象,并将对象反序列化。它的返回值为Object,因此,需要将它转换成合适的数据类型。
ObjectInputStream In = new ObjectInputStream(new FileInputStream("1.txt")); Test o = (Test)In.readObject(); System.out.println(o); //读取后输出实例理解
实例理解
Test.java(类想要进行序列化操作,必须实现Serializable接口继承)
package Sentiment.unserialize.demo01; import java.io.Serializable; public class Test implements Serializable { private String name; private int age; public Test() { } public Test(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Test{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Serializable.java
package Sentiment.unserialize.demo01; import java.io.*; public class Serializable { public static void main(String[] args) throws IOException { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt")); out.writeObject(new Test("Sentiment",10)); out.close(); } }
UnSerializable.java
package Sentiment.unserialize.demo01; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class UnSerializable { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream In = new ObjectInputStream(new FileInputStream("1.txt")); Test o = (Test)In.readObject(); System.out.println(o); } }
运行Serializable.java后便得到二进制字节码文件内容
此时在运行UnSerializable.java便得到了二进制字节码反序列化后的内容
每个可序列化的类在序列化时都会关联一个版本号 , 这个版本号就是 serialVersionUID 属性
serialVersionUID 属性必须通过 static final long 修饰符来修饰 。
如果可序列化的类未声明 serialVersionUID 属性 , 则 Java 序列化时会根据类的各种信息来计算默认的 serialVersionUID 值 . 但是 Oracle 官方文档强烈建议所有可序列化的类都显示声明 serialVersionUID 值 .
实例理解
在Test.java中定义serialVersionUID
其值为1
package Sentiment.unserialize.demo01; import java.io.Serializable; public class Test implements Serializable { public static final long serialVersionUID = 1L; //定义serialVersionUID private String name; private int age; public Test() { } public Test(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Test{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
此时运行Serializable.java进行序列化操作
运行完毕后将serialVersionUID
的值定义为2—>public static final long serialVersionUID = 2L;,在运行UnSerializable.java会报错
Transient( 瞬态变量 )是一个 Java 关键词 , 它用于标记类的成员变量在持久化到字节流时不要被序列化 ; 在通过网络套接字流传输字节流时 , transient 关键词标记的成员变量不会被序列化 。此为被static修饰的静态变量也不参与序列化操作。
将Test.java中的name
和age
变量前分别加上transient
和static
byte[]
를 Java 객체 Java Object
Serialization APIObjectOutputStream
예:
package Sentiment.unserialize.demo01; import java.io.Serializable; public class Test implements Serializable { public static final long serialVersionUID = 1L; //定义serialVersionUID private transient String name; //加上transient private static int age; //加上static public Test() { } public Test(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Test{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
writeObject()
메서드도 제공합니다. private void readObject(java.io.ObjectInputStream a) throws IOException, ClassNotFoundException{ a.defaultReadObject(); Runtime.getRuntime().exec("calc.exe"); }
ObjectInputStream
바이트 입력 스트림 개체는 파일의 이진 바이트 시퀀스를 역직렬화합니다(FileInputStream과 결합)
예: 🎜rrreee🎜또한 ObjectInputStream은readObject()
메서드를 제공합니다. 스트림의 다음 개체를 제거하고 개체를 역직렬화합니다. 반환 값은 Object이므로 적절한 데이터 유형으로 변환해야 합니다. 🎜rrreee🎜이해의 예🎜🎜Test.java(클래스가 직렬화 작업을 수행하려면 직렬화 가능 인터페이스 상속을 구현해야 함)🎜rrreee🎜Serialized.java🎜rrreee🎜 UnSerialized.java🎜rrreee🎜Serialized.java를 실행한 후 바이너리 바이트 코드 파일 내용 가져오기🎜🎜🎜 🎜이때 UnSerialized.java를 실행하면 바이너리 바이트코드의 역직렬화된 내용을 얻을 수 있습니다🎜🎜🎜🎜serialVersionUID🎜serialVersionUID
를 정의하고 그 값은 1🎜rrreee🎜직렬화 작업을 위해 현재 Serialized.java를 실행합니다🎜 🎜실행 후 , serialVersionUID
값을 2—>public static final long serialVersionUID = 2L;로 정의하면 UnSerialized.java🎜🎜🎜🎜Transient(일시적 변수)🎜🎜Transient(일시적 변수)는 Java 키워드입니다. 바이트 스트림에 지속될 때 직렬화되지 않는 클래스의 멤버 변수를 표시하는 데 사용됩니다. 네트워크 소켓 스트림을 통해 바이트 스트림을 전송할 때 임시 키워드로 표시된 멤버 변수는 직렬화되지 않습니다. 이는 static으로 수정되는 정적 변수이며 직렬화 작업에 참여하지 않습니다. 🎜🎜이해 예🎜🎜Test.java의 name
및 age
변수 앞에 각각 transient
및 static
를 추가하세요. >🎜rrreee🎜이때 Serialized.java, UnSerialized.java가 실행되고 출력결과는 Sentiment—>null, 10—>0🎜🎜🎜🎜🎜readObject() 메소드 재작성🎜🎜사용자에게 공식적으로 허용됩니다. 클래스의 readObject() 메서드를 재정의하면 재정의된 메서드는 역직렬화 중에 현재 클래스 객체를 재구성합니다. 사용자는 재정의된 readObject() 메서드에서 defaultReadObject() 메서드만 구현하면 됩니다. reverse 직렬화 프로세스는 정상적으로 실행됩니다. 🎜🎜예시 이해🎜🎜 defaultReadObject() 메서드 호출을 구현하고 Test 클래스에서 메서드를 다시 작성합니다. 직렬화 및 역직렬화 작업 후에 명령을 실행할 수 있습니다.🎜rrreee🎜🎜🎜위 내용은 Java 직렬화 및 역직렬화를 적용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!