public class ObjectIOTest {
public static void write() {
/*
* 스트림: 바이트단위 출력스트림
* 필터스트림: 객체단위출력스트림
* 목적지 : 파일
*/
String fileName = "a.ser";
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(fileName));
oos.writeObject(new Date());
} catch (IOException e) {
e.printStackTrace();
} finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
write();
}
}
public class ObjectIOTest {
public static void write() {
/*
* 스트림: 바이트단위 출력스트림
* 필터스트림: 객체단위출력스트림
* 목적지 : 파일
*/
String fileName = "a.ser";
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(fileName));
oos.writeObject(new Date());
Customer c = new Customer("id1", "p1", "n1", "a1");
// 직렬화 위해 Customer.java.에 implements Serializable
oos.writeObject(c);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void read() {
String fileName = "a.ser";
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(fileName));
Object obj1 = ois.readObject(); // 객체를 녹이는 과정
System.out.println(obj1.toString());
Object obj2 = ois.readObject();
System.out.println(obj2); // obj2.toString() 자동호출됨
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
write();
read();
}
}
public class Customer extends Person implements Serializable {
public static void main(String[] args) {
Customer c = new Customer("id1", "p1", "n1", "a1");
System.out.println(c);
}
}
결과 첫번째 줄 : 얼린 시간의 시간
결과 블록부분 : 부모쪽은 serializable 안되서 null 값이 나왔음
- 부모쪽에서 제공되는 멤버변수는 객체 직렬화의 대상이 아님
customer가 Serializable를 구현해서 부모꺼는 직렬화가 안됨.
부모쪽에서 제공되는걸 직렬화하고 싶으면 Person에 implements Serializable 해야함.
부모쪽에 하면 Customer도 직렬화 가능하다
- 멤버변수로 쓰지말고 각 메서드마다 호출, 가공할 것
public class Person implements Serializable {
public class Customer extends Person {
위와 같이 수정하면 결과값 아래와 같이 변경된다
public class Customer extends Person {
private String id;
transient private String pwd;
※ 직렬화될 때 transient 넣어서 null 값으로 보이게 할 수 있음
package ch18.sec10;
import java.io.Serializable;
public class Member implements Serializable {
private static final long serialVersionUID = -622284561026719240L;
private String id;
private String name;
public Member(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() { return id + ": " + name; }
}
위의 예제를 보면 Member는 Serializable 인터페이스를 구현하고 있다. 자바는 Serializable 인터페이스를 구현한 클래스만 직렬화할 수 있도록 제한한다. Serializable 인터페이스는 멤버가 없는 빈 인터페이스지만, 객체를 직렬화할 수 있다고 표시하는 역할을 한다. 객체가 직렬화될 때 인스턴스 필드값은 직렬화 대상이지만 정적 필드값과 transient로 선언된 필드값은 직렬화에서 제외되므로 출력되지 않는다.
public class xxx implements Serializable {
public int field1;
protected int field2;
int field3;
private field4;
public static int field5; // 정적필드는 직렬화에서 제외
transient int field6; // transient로 선언된 필드는 직렬화에서 제외
}
직렬화하면 일렬로 늘어선 바이트 데이터 아래와 같이 된다.
field1 | field2 | field3 | field4 |
※ serialVersionUID 필드
직렬화할 때 사용된 클래스와 역직렬화할 때 사용된 클래스는 기본적으로 동일한 클래스여야 한다.
만약 클래스의 이름이 같더라도 클래스의 내용이 다르면 역직렬화에 실패한다.
public class Member implemets Serializble {
int field1;
int field2;
}
// 위의 Member 클래스로 생성한 객체를 직렬화하면
// 아래의 Member 클래스로 역직렬화할 수 없다. 아래 클래스에는 field3;가 있기 때문
public class Member implemets Serializble {
int field1;
int field2;
int field3;
}
클래스 내용이 다르다 할지라도 직렬화된 필드를 공통으로 포함하고 있다면 역직렬화할 수 있는 방법이 있다.
두 클래스가 동일한 serialVersionUID 상수값을 가지고 있으면 된다.
public class Member implemets Serializble {
static final long serialVersionUID = 1;
int field1;
int field2;
}
// 직렬화 가능
public class Member implemets Serializble {
static final long serialVersionUID = 1;
int field1;
int field2;
int field3;
}
※ 이클립스 serialVersionUID 자동 생성 기능 있음, 두번째꺼 누르면 된다/
'언어 > Java' 카테고리의 다른 글
기본자료형과 참조형의 차이 (0) | 2023.08.10 |
---|---|
Product 예제 4 (0) | 2023.08.09 |
필터스트림, 객체직렬화 (0) | 2023.08.09 |
메타클래스, File 정보 가져오기 (0) | 2023.08.09 |
FileCopy 예제 (0) | 2023.08.09 |