▣ Serialization
- 메모리상에 생성된 클래스객체의 멤버 변수의 값을 네트웍이나 파일로 저장할 수 있는 기능 제공
- 객체직렬화가 필요한 객체는 반드시 Serializable 인터페이스를 구현해야 한다. 하지만 Serializable 인터페이스는 객체 직렬화가 제공되어야 함을 자바 가상머신에게 알려주는 열활만 하며 별도로 구현해야하는 메소드는 없다.
- 객체 직렬화를 실행 할때 관련된 클래스도 객체 직렬화를 수행한다.
- RMI를 통한 원격객체 통신, Beans 설계시 상태 정보 저장등에 효율적으로 쓰인다.
1. 기본적인 Object Serialization
import java.io.*;
public class UnitIn implements Serializable{
private int i;
private String name;
public UnitIn(int d, String s){
i = d;
name = s;
System.out.println(name + " 생성자가 호출되었습니다: ");
}
public String toString(){
return "이름은 " + name + " : " + i;
}
public static void main(String args[]){
UnitIn u1, u2;
u1 = new UnitIn(1,"개구리 소년 : 왕눈이");
u2 = new UnitIn(2,"개구리 소녀 : 아로미");
try{
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("unit.ser"));
out.writeObject(u1);
out.writeObject(u2);
out.close();
System.out.println("객체를 파일에 기록했습니다.");
} catch(Exception e) {
e.printStackTrace();
}
}
}
2. 레퍼런스 변수의 Object Serialization
- Reference 변수가 가리키고 있는 클래스도 Serializable Interface를 구현해야 함.
-------------------- Unit1.java --------------------
import java.io.*;
public class Unit1 implements Serializable{
private String name;
private SubUnit[] unit_array;
public Unit1(String s, SubUnit[] u_arr){
name = s;
unit_array = u_arr;
System.out.println("생성자가 호출되었습니다: " + name);
}
public String toString(){
String retStr;
retStr = "이름은 " + name + " -> ";
for(int i=0; i < unit_array.length; i++)
retStr += unit_array[i].toString() + " : ";
return retStr;
}
public static void main(String args[]){
Unit1 u1, u2;
SubUnit[] sub1 = { new SubUnit("개구리"), new SubUnit("왕눈이"), new SubUnit("아로미") };
SubUnit[] sub2 = { new SubUnit("슈퍼톡톡"), new SubUnit("둥가")};
u1 = new Unit1("연못", sub1);
u2 = new Unit1("영어", sub2);
try{
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("unit.ser"));
out.writeObject(u1);
out.writeObject(u2);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("unit.ser"));
Unit1 u3, u4;
u3 = (Unit1)in.readObject();
u4 = (Unit1)in.readObject();
System.out.println("다시 복원합니다");
System.out.println(u3);
System.out.println(u4);
} catch(Exception e) {
e.printStackTrace();
}
}
}
-------------------- SubUnit.java --------------------
import java.io.*;
public class SubUnit implements Serializable{
private String unit_name;
public SubUnit(String s){
unit_name = s;
}
public String toString(){
return unit_name;
}
}
3-1. transient 키워드는 직렬화의 대상에서 변수를 제외시켜준다.
-------------------- Unit3.java --------------------
import java.io.*;
public class Unit3 implements Serializable{
private String name;
transient String passwd;
public Unit3(String s, String p){
name = s;
passwd = p;
System.out.println(name + " 생성자가 호출되었습니다");
}
public String toString(){
return "이름은 " + name + " : 패스워드 : " + passwd;
}
public static void main(String args[]){
Unit3 u1, u2;
u1 = new Unit3("강북구","1000");
u2 = new Unit3("강남구","2000");
try{
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("unit.ser"));
out.writeObject(u1);
out.writeObject(u2);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("unit.ser"));
Unit3 u3, u4;
u3 = (Unit3)in.readObject();
u4 = (Unit3)in.readObject();
System.out.println("----------- 다시 복원한 후의 값 ----------");
System.out.println(u3);
System.out.println(u4);
} catch(Exception e) {
e.printStackTrace();
}
}
}
3-2. 객체 직렬화 데이터 클래스의 분리
------------------ Serial1.java ------------------
import java.io.*;
public class Serial1 {
public static void main(String[] args) throws IOException {
Person p = new Person("너구리", 20, "오동통하고 쫄깃함");
System.out.println();
System.out.println("객체 직렬화");
System.out.println("---------------------------------");
System.out.println("Person's 이름: " + p.name);
System.out.println("Person's 나이: " + p.age);
System.out.println("Person's 비고: " + p.temp);
System.out.println("---------------------------------");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("rich.ser"));
oos.writeObject(p);
oos.flush();
System.out.println();
System.out.println("객체 직렬화가 다 되었습니다.");
p = null;
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("rich.ser"));
try {
p = (Person) ois.readObject();
} catch(ClassNotFoundException cnfe) {
System.err.println("Persion 클래스를 찾지 못했습니다.");
}
System.out.println();
System.out.println("객체 복원");
System.out.println();
System.out.println("객체 복원 후의 결과");
System.out.println("---------------------------------");
System.out.println("Person's 나이: " + p.name);
System.out.println("Person's 이름: " + p.age);
System.out.println("Person's 비고: " + p.temp);
System.out.println("---------------------------------");
}
}
class Person implements Serializable {
public String name;
public int age;
public transient String temp;
public Person(String name, int age, String temp) {
this.name = name;
this.age = age;
this.temp = temp;
}
}
4. 동일한 클래스 명에서의 충돌을 막기 위한 클래스의 버전 관리
- serialver 툴 사용하기
------------------ Serial2.java 클래스의 수정 ------------------
import java.io.*;
public class Serial2 {
public static void main(String[] args) throws IOException {
Person p = null;
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("rich.ser"));
try {
p = (Person) ois.readObject();
} catch(ClassNotFoundException cnfe) {
System.err.println("Persion 클래스를 찾지 못했습니다.");
}
System.out.println();
System.out.println("객체 복원");
System.out.println();
System.out.println("객체 복원 후의 결과");
System.out.println("---------------------------------");
System.out.println("Person's 나이: " + p.name);
System.out.println("Person's 전화번호: " + p.phone);
System.out.println("Person's 이름: " + p.age);
System.out.println("Person's 비고: " + p.temp);
System.out.println("---------------------------------");
}
}
class Person implements Serializable {
public String name;
public String phone;
public int age;
public transient String temp;
public Person(String name, String phone, int age, String temp) {
this.name = name;
this.phone = phone;
this.age = age;
this.temp = temp;
}
}
------------------ Serial3.java ------------------
import java.io.*;
public class Serial3 {
public static void main(String[] args) throws IOException {
Person p = null;
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("rich.ser"));
try {
p = (Person) ois.readObject();
} catch(ClassNotFoundException cnfe) {
System.err.println("Persion 클래스를 찾지 못했습니다.");
}
System.out.println();
System.out.println("객체 복원");
System.out.println();
System.out.println("객체 복원 후의 결과");
System.out.println("---------------------------------");
System.out.println("Person's 나이: " + p.name);
System.out.println("Person's 전화번호: " + p.phone);
System.out.println("Person's 이름: " + p.age);
System.out.println("Person's 비고: " + p.temp);
System.out.println("---------------------------------");
}
}
class Person implements Serializable {
public String name;
public String phone;
public int age;
public transient String temp;
static final long serialVersionUID = 5126197534689646959L;
public Person(String name, String phone, int age, String temp) {
this.name = name;
this.phone = phone;
this.age = age;
this.temp = temp;
}
}
5. 객체의 네트워크 전송
-------------------- Unit.java --------------------
import java.io.*;
public class Unit implements Serializable{
private int i;
private String name;
public Unit(int d, String s){
i = d;
name = s;
}
public String toString(){
return "이름은 " + name + " : " + "좋아하는 숫자 " + i;
}
}
-------------------- Client.java --------------------
//실행 : java Client 211.44.123.164 4000
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws IOException {
try {
if (args.length != 2) throw new IllegalArgumentException("인자의 수가 다름");
String host = args[0];
int port = Integer.parseInt(args[1]);
System.out.println(host + " : " + port);
Socket s = new Socket(host, port);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
Unit u = new Unit(1,"너구리");
oos.writeObject(u);
oos.flush();
s.close();
}
catch (Exception e) {
System.err.println(e);
System.err.println("사용법: java Client <hostname> <port:4000>");
}
}
}
-------------------- Server.java --------------------
import java.io.*;
import java.net.*;
import java.util.*;
public class Server{
public final static int SERVER_PORT = 4000;
public static void main(String args[]){
ServerSocket serverSock;
Socket sock;
ObjectInputStream ois;
try{
serverSock = new ServerSocket(SERVER_PORT);
while(true){
System.out.println("서버가 작동 되었습니다.");
sock = serverSock.accept();
ois = new ObjectInputStream(sock.getInputStream());
Unit u = (Unit)ois.readObject();
System.out.println("네트워크 전송된 객체는 " + u.toString());
sock.close();
serverSock.close();
}
} catch(IOException e){
System.err.println(e);
} catch (ClassNotFoundException e){
System.err.println(e);
}
}
}
[출처] [본문스크랩] 객체직렬화(Serialization)|작성자 파랑하늘