자바 직렬화
Java는 객체 직렬화 메커니즘을 제공합니다. 이 메커니즘에서 객체는 객체의 데이터, 객체 유형에 대한 정보 및 객체 유형에 저장된 데이터를 포함하는 바이트 시퀀스로 표현될 수 있습니다.
직렬화된 개체를 파일에 쓴 후 파일에서 읽고 역직렬화할 수 있습니다. 즉, 개체의 형식 정보, 개체의 데이터 및 개체의 데이터 형식을 사용할 수 있습니다. 메모리에 새로운 객체가 있습니다.
전체 프로세스는 JVM(Java Virtual Machine)에 독립적입니다. 즉, 한 플랫폼에서 직렬화된 객체가 완전히 다른 플랫폼에서 객체를 역직렬화할 수 있습니다.
클래스 ObjectInputStream 및 ObjectOutputStream은 객체 직렬화 및 역직렬화를 위한 메서드가 포함된 상위 수준 데이터 스트림입니다.
ObjectOutputStream 클래스에는 다양한 데이터 유형을 작성하기 위한 여러 작성 방법이 포함되어 있지만 한 가지 특별한 방법은 예외입니다.
public final void writeObject(Object x) throws IOException
위의 방법은 객체를 직렬화하여 출력 스트림으로 보냅니다. 유사한 ObjectInputStream 클래스에는 개체를 역직렬화하기 위한 다음 메서드가 포함되어 있습니다.
public final Object readObject() throws IOException, ClassNotFoundException
이 메서드는 스트림에서 다음 개체를 가져와 개체를 역직렬화합니다. 반환 값은 Object이므로 적절한 데이터 유형으로 변환해야 합니다.
Java에서 직렬화가 어떻게 작동하는지 보여주기 위해 이전 튜토리얼에서 언급한 Employee 클래스를 사용하겠습니다. 직렬화 가능 인터페이스를 구현하는 다음 Employee 클래스를 정의한다고 가정하겠습니다.
public class Employee implements java.io.Serializable { public String name; public String address; public transient int SSN; public int number; public void mailCheck() { System.out.println("Mailing a check to " + name + " " + address); } }
클래스의 객체가 성공적으로 직렬화되려면 두 가지 조건이 충족되어야 합니다.
클래스는 java.io.Serialized 객체를 구현해야 합니다.
이 클래스의 모든 속성은 직렬화 가능해야 합니다. 속성이 직렬화 가능하지 않은 경우 해당 속성은 임시로 표시되어야 합니다.
Java 표준 클래스가 직렬화 가능한지 알고 싶다면 해당 클래스에 대한 설명서를 확인하세요. 클래스의 인스턴스가 직렬화될 수 있는지 확인하는 것은 매우 간단합니다. 클래스가 java.io.Serialized 인터페이스를 구현하는지 확인하면 됩니다.
객체 직렬화
ObjectOutputStream 클래스는 객체를 직렬화하는 데 사용됩니다. 다음 SerializeDemo 예제는 Employee 객체를 인스턴스화하고 객체를 파일로 직렬화합니다.
프로그램이 실행되면 Employee.ser라는 파일이 생성됩니다. 프로그램은 어떠한 출력도 생성하지 않지만 코드를 연구하면 프로그램이 수행하는 작업을 이해할 수 있습니다.
참고: 객체를 파일로 직렬화할 때 Java의 표준 규칙에 따라 파일에 .ser 확장자가 부여됩니다.
import java.io.*; public class SerializeDemo { public static void main(String [] args) { Employee e = new Employee(); e.name = "Reyan Ali"; e.address = "Phokka Kuan, Ambehta Peer"; e.SSN = 11122333; e.number = 101; try { FileOutputStream fileOut = new FileOutputStream("/tmp/employee.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(e); out.close(); fileOut.close(); System.out.printf("Serialized data is saved in /tmp/employee.ser"); }catch(IOException i) { i.printStackTrace(); } } }
Deserialization 객체
아래 DeserializeDemo 프로그램은 deserialization을 인스턴스화하고 /tmp/employee.ser는 Employee 객체를 저장합니다.
import java.io.*; public class DeserializeDemo { public static void main(String [] args) { Employee e = null; try { FileInputStream fileIn = new FileInputStream("/tmp/employee.ser"); ObjectInputStream in = new ObjectInputStream(fileIn); e = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println("Employee class not found"); c.printStackTrace(); return; } System.out.println("Deserialized Employee..."); System.out.println("Name: " + e.name); System.out.println("Address: " + e.address); System.out.println("SSN: " + e.SSN); System.out.println("Number: " + e.number); } }
위 프로그램의 컴파일 및 실행 결과는 다음과 같습니다.
Deserialized Employee... Name: Reyan Ali Address:Phokka Kuan, Ambehta Peer SSN: 0 Number:101
여기서 다음 사항에 유의해야 합니다.
readObject() 메서드의 try/catch 코드 블록은 ClassNotFoundException 예외를 catch하려고 시도합니다. JVM이 객체를 역직렬화할 수 있으려면 바이트코드를 찾을 수 있는 클래스여야 합니다. JVM이 객체의 직렬화 해제 중에 클래스를 찾을 수 없으면 ClassNotFoundException이 발생합니다.
readObject() 메서드의 반환 값은 Employee 참조로 변환됩니다.
객체를 직렬화하면 SSN 속성의 값은 111222333이지만 속성의 수명이 짧기 때문에 값이 출력 스트림으로 전송되지 않습니다. 따라서 역직렬화 후 Employee 개체의 SSN 속성은 0입니다.