객체의 직렬화 : DB개념이 나오기전에는 파일을 모두 이와 같이 저장함
메모리에 생성된 클래스를 객체의 멤버변수의 현재 상태를 그대로 보존해서 파일에 저장하거나 네트워크를 통해 전달할 수 있는 기능
오로지 바이트 단위로만 데이터를 송수신 가능하다. 즉, 자바 시스템안에서 사용되는 데이터를 다른곳에서도 사용가능하도록
바이트 형태로 변환하는 기능과 바이트로 변환된 데이터를 다시 객체로 변환하는 (역직렬화) 를 포함하여 이야기한다.
장점은 객체 자체의 내용을 입출력 형식에 구애받지 않고 객체를 저장함으로써 영속성(프로그램을 종료해도 저장되어 있음)을 제공가능하며
객체 자체를 네트워크를 통해서 손쉽게 교환할 수 있다.
implements Serializable(인터페이스)로 구현(단, 메소드가 없다). 선언만 하면 됨
Collenction은 기본적으로 Serializable 구현된 인터페이스로 지님. 그래서 아래 코드에 구현 내용이 없어도 가능
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.Hashtable;
public class Test1 {
public static void main(String[] args) {
try {
//Map 생성
Hashtable<String, String> h = new Hashtable<String, String>();
h.put("1", "배수지");
h.put("2", "김태리");
h.put("3", "천송이");//직렬화
//아웃풋파일 생성(파일은 character방식이라 h를 바로 넣을 수 없음. 유니코드로 된 데이터만 가능)
FileOutputStream fos = new FileOutputStream("d:\\doc\\out7.txt");
//파일을 메모리상에 있는 binary 형식으로 저장.
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(h);//upcast. 클래스는 데이터 타입이 Object
oos.close();
fos.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
역 직렬화 : 직렬화된 바이트형태의 데이터를 읽어와 객체로 변환하여 자바에서 사용가능하도록 만드는 기능
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Hashtable;
import java.util.Iterator;
public class Test2 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("d:\\doc\\out7.txt");//out7파일에 저장된건 Hashtable
ObjectInputStream ois = new ObjectInputStream(fis);
Hashtable<String, String> h = (Hashtable<String, String>)ois.readObject();//downcast
Iterator<String> it = h.keySet().iterator();
while(it.hasNext()){
String key = it.next();
String value = h.get(key);
System.out.println( key + " " + value);
}
fis.close();
ois.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
역직렬화는 개념을 누구나 꺼낼 수 있음. password와 같은 개념은 그때 그때 물어보게 해야한다
해당 예제에서는 age변수에 transient를 설정하면 -> default 값이 나옴
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Test3 {
public static void main(String[] args) {
try {
//직렬화
FileOutputStream fos = new FileOutputStream("d:\\doc\\score.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//MyData ob = new MyData("배수지", 30);
oos.writeObject(new MyData("배수지",25,60));//클래스 객체 생성해서 바로 넣어주려고 오버로딩한 생성자를 만든 것
oos.writeObject(new MyData("박신혜",29,60));
oos.writeObject(new MyData("김태리",29,90));
oos.writeObject(new MyData("천송이",40,80));
oos.close();
fos.close();
//역직렬화
FileInputStream fis = new FileInputStream("d:\\doc\\score.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
MyData ob = null;//클래스의 초기값은 null
while(true){
ob = (MyData)ois.readObject();//downcast
if(ob==null){//null이면 더이상 출력할 MyData없음
break;
}
System.out.println(ob.toString());
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
implements Serializable가 반드시 작성되어야 함.
선언해주지 않는다면 직렬화가 되지 않아 writeObject로 입력 불가능
import java.io.Serializable;
public class MyData implements Serializable{//VO역할 하면 원래 GETTER, SETTER, 변수들만 있어야 하지만, 생성자 추가할 거임.
private static final long serialVersionUID = 1L;
private String name;
private transient int age;
private int score;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public MyData(String name,int age ,int score){//오버로딩된 생성자. 초기화
this.name = name;
this.score = score;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return String.format("%6s %4d %4d점",name,age,score);
}
}
Externalizable: Serializable 인터페이스에 하위 인터페이스같은 기능을 하되 좀 더 완벽한 제어가 가능함
writeExternal(), readExternal() 메소드를 정의해야 함
Externalizable보다 Serializable을 많이 사용함
import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
class DataTest implements Externalizable{
String name;
int age;
public DataTest(){}//기본생성자
public DataTest(String name, int age){//오버로딩된 생성자
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + ":" + age;
}
//호출 하지 않아도 자동적으로 실행되는 메소드 : readExternal(), writeExternal()
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
name = (String)in.readObject();//downcast
age = in.readInt();//downcast 안해도 됨. 메소드에서 정수형으로 반환
System.out.println("readExternal....");
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeInt(age);
System.out.println("writeExternal....");
}
}
public class Test4 {
public static void main(String[] args) {
try {
DataTest ob = new DataTest("배수지", 25);//넣을 땐 오버로딩된 생성자로 객체 생성.
FileOutputStream fos = new FileOutputStream("d:\\doc\\out8.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(ob);
fos.close();
oos.close();
FileInputStream fis = new FileInputStream("d:\\doc\\out8.txt");
ObjectInputStream ois = new ObjectInputStream(fis);//직렬화 되었기 때문에 ObjectInputStream로 감싸줘야함
DataTest ob1 = (DataTest)ois.readObject();//꺼낼 때는 기본생성자로!
System.out.println(ob1.toString());
fis.close();
oos.close();
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
다시 읽어보기) 자바 직렬화, 그것이 알고싶다. 훑어보기편 http://woowabros.github.io/experience/2017/10/17/java-serialize.html
'Dev > Java' 카테고리의 다른 글
[java] 채팅프로그램 만들기 (0) | 2019.01.31 |
---|---|
[java] 윈도우,swing (0) | 2019.01.31 |
[java] Stream (0) | 2019.01.30 |
[java] 스레드 (0) | 2019.01.28 |
[java] ArrayList, List, Map, Generic, Exception (0) | 2019.01.27 |