직렬화와 역직렬화에 대하여 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화와 역직렬화에 대하여 직렬화 가능 클래스의 선언 방법
01. 직렬화와 역직렬화에 대하여 객체의 직렬화 직렬화와 역직렬화 • 용어 설명 직렬화(serialization) : 객체를 스트림으로 만드는 작업 - 역직렬화(deserialization) : 스트림을 객체로 만드는 작업
01. 직렬화와 역직렬화에 대하여 객체의 직렬화 직렬화와 역직렬화 [예제 17-1] 객체를 직렬화하는 프로그램과 역직렬화하는 프로그램 객체를 직렬화하는 프로그램 import java.io.*; import java.util.GregorianCalendar; import java.util.Calendar; class ObjectInputExample1 { public static void main(String args[]) { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream("output.dat")); while (true) { GregorianCalendar calendar = (GregorianCalendar) in.readObject(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; int date = calendar.get(Calendar.DATE); System.out.println(year + "/" + month + "/" + date); } catch (FileNotFoundException fnfe) { System.out.println("파일이 존재하지 않습니다."); catch (EOFException eofe) { System.out.println("끝"); catch (IOException ioe) { System.out.println("파일을 읽을 수 없습니다."); catch (ClassNotFoundException cnfe) { System.out.println("해당 클래스가 존재하지 않습니다."); finally { in.close(); catch (Exception e) { 객체를 역직렬화하는 프로그램 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 객체를 역직렬화하는 부분 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.io.*; import java.util.GregorianCalendar; class ObjectOutputExample1 { public static void main(String args[]) { ObjectOutputStream out = null; try { out = new ObjectOutputStream( new FileOutputStream("output.dat")); out.writeObject(new GregorianCalendar(2006, 0, 14)); out.writeObject(new GregorianCalendar(2006, 0, 15)); out.writeObject(new GregorianCalendar(2006, 0, 16)); } catch (IOException ioe) { System.out.println("파일로 출력할 수 없습니다."); finally { out.close(); catch (Exception e) { 객체를 직렬화하는 부분 객체를 직렬화해서 파일에 저장합니다. 파일로부터 객체를 역직렬화해서 출력합니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 선언 • JDK 라이브러리의 직렬화 가능 클래스 구분 방법 java.io.Seiralizable 인터페이스를 구현하는 클래스는 직렬화 가능 클래스 - java.io.Seiralizable 인터페이스를 구현하지 않는 클래스는 직렬화 불가능 클래스 • 직렬화 가능 클래스의 선언 java.io.Seiralizable 인터페이스를 구현하는 것만으로 충분할까요?
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 선언 [예제 17-2] 직렬화 가능 클래스를 만드는 예 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class GoodsStock implements java.io.Serializable { String code; int num; GoodsStock(String code, int num) { this.code = code; this.num = num; } void addStock(int num) { this.num += num; int subtractStock(int num) throws Exception { if (this.num < num) throw new Exception("재고가 부족합니다."); this.num -= num; return num; 직렬화 가능 클래스 직렬화가 불가능한 클래스 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class GoodsStock { // 재고 정보 클래스 String code; int num; GoodsStock(String code, int num) { this.code = code; this.num = num; } void addStock(int num) { this.num += num; int subtractStock(int num) throws Exception { if (this.num < num) throw new Exception("재고가 부족합니다."); this.num -= num; return num;
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 선언 [예제 17-3] GoodsStock 객체를 직렬화하고 역직렬화하는 프로그램 GoodsStock 객체를 직렬화하는 프로그램 import java.io.*; class ObjectInputExample2 { public static void main(String args[]) { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream("output2.dat")); while (true) { GoodsStock obj = (GoodsStock) in.readObject(); System.out.println(“상품코드:" + obj.code + “\t상품수량:" + obj.num); } catch (FileNotFoundException fnfe) { System.out.println("파일이 존재하지 않습니다."); catch (EOFException eofe) { System.out.println("끝"); catch (IOException ioe) { System.out.println(“파일을 읽을 수 없습니다.”); catch (ClassNotFoundException cnfe) { System.out.println("해당 클래스가 존재하지 않습니다."); finally { in.close(); catch (Exception e) { GoodsStock 객체를 역직렬화하는 프로그램 객체를 역직렬화 하는 부분 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.io.*; class ObjectOutputExample2 { public static void main(String args[]) { ObjectOutputStream out = null; try { out = new ObjectOutputStream(new FileOutputStream("output2.dat")); out.writeObject(new GoodsStock(“70101”, 100)); out.writeObject(new GoodsStock(“70102”, 50)); out.writeObject(new GoodsStock(“70103”, 200)); } catch (IOException ioe) { System.out.println(“파일로 출력할 수 없습니다.”); finally { out.close(); catch (Exception e) { 객체를 직렬화하는 부분 [직렬화가 불가능한 GoodsStock 클래스와 함께 컴파일하고 실행했을 때의 결과] 컴파일은 정상적으로 되지만, 프로그램을 실행할 때 에러가 발생합니다. [직렬화가 가능한 GoodsStock 클래스와 함께 컴파일하고 실행했을 때의 결과] 컴파일도 정상적으로 되고, 프로그램의 실행도 정상적으로 됩니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 대상 • 생성자, 메소드, 정적 필드는 직렬화 대상이 아닙니다. 직렬화 대상에서 제외시키고 싶은 인스턴스 필드가 있으면 어떻게 해야할까요?
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 대상 [예제 17-4] transient 필드를 포함하는 직렬화 가능 클래스의 예 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class BBSItem implements java.io.Serializable { // 게시물 클래스 static int itemNum = 0; // 게시물의 수 String writer; // 글쓴이 transient String passwd; // 패스워드 String title; // 제목 String content; // 내용 BBSItem(String writer, String passwd, String title, String content) { this.writer = writer; this.passwd = passwd; this.title = title; this.content = content; itemNum++; } void modifyContent(String content, String passwd) { if (!passwd.equals(this.passwd)) return;
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 대상 [예제 17-5] BBSItem 객체를 직렬화하고 역직렬화하는 프로그램 BBSItem 객체를 직렬화하는 프로그램 import java.io.*; class ObjectInputExample3 { public static void main(String args[]) { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream("output3.dat")); BBSItem obj = (BBSItem) in.readObject(); System.out.println(“전체게시물의 수: " + obj.itemNum); System.out.println(“글쓴이: " + obj.writer); System.out.println(“패스워드: " + obj.passwd); System.out.println(“제목: " + obj.title); System.out.println(“내용: " + obj.content); } catch (FileNotFoundException fnfe) { System.out.println("파일이 존재하지 않습니다."); catch (EOFException eofe) { System.out.println(“끝"); catch (IOException ioe) { System.out.println("파일을 읽을 수 없습니다."); catch (ClassNotFoundException cnfe) { System.out.println("해당 클래스가 존재하지 않습니다."); finally { in.close(); catch (Exception e) { BBSItem 객체를 역직렬화하는 프로그램 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 객체를 역직렬화하는 부분 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.io.*; class ObjectOutputExample3 { public static void main(String args[]) { ObjectOutputStream out = null; try { out = new ObjectOutputStream(new FileOutputStream("output3.dat")); BBSItem obj = new BBSItem(“최선희”, “sunshine”, “정모합시다”, “이번주 주말 어떠세요?”); System.out.println(“전체게시물의 수: " + obj.itemNum); System.out.println(“글쓴이: " + obj.writer); System.out.println(“패스워드: " + obj.passwd); System.out.println(“제목: " + obj.title); System.out.println(“내용: " + obj.content); out.writeObject(obj); } catch (IOException ioe) { System.out.println("파일로 출력할 수 없습니다."); finally { out.close(); catch (Exception e) { 객체를 직렬화하는 부분
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 대상 • 직렬화 대상에서 제외되는 transient 필드
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 불가능한 필드 타입 [예제 17-6] 직렬화 불가능 필드를 포함하는 직렬화 가능 클래스의 예 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class BBSItem implements java.io.Serializable { // 게시물 클래스 static int itemNum = 0; // 게시물의 수 String writer; // 글쓴이 transient String passwd; // 패스워드 String title; // 제목 String content; // 내용 Object attachment; // 첨부파일 BBSItem(String writer, String passwd, String title, String content) { this.writer = writer; this.passwd = passwd; this.title = title; this.content = content; itemNum++; } void modifyContent(String content, String passwd) { if (!passwd.equals(this.passwd)) return; void addAttachment(Object attachment) { // 파일을 첨부한다 this.attachment = attachment;
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 불가능한 필드 타입 [예제 17-7] 게시물 클래스의 객체를 직렬화하고 역직렬화하는 프로그램 BBSItem 객체를 직렬화하는 프로그램 BBSItem 객체를 역직렬화하는 프로그램 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.io.*; class ObjectOutputExample4 { public static void main(String args[]) { ObjectOutputStream out = null; try { out = new ObjectOutputStream(new FileOutputStream("output4.dat")); BBSItem obj = new BBSItem(“이석영”, “moonlight”, “자료 파일입니다.”, “첨부 파일을 참고하십시오.”); obj.addAttachment(new Object()); System.out.println(“전체게시물의 수: " + obj.itemNum); System.out.println(“글쓴이: " + obj.writer); System.out.println(“패스워드: " + obj.passwd); System.out.println(“제목: " + obj.title); System.out.println(“내용: " + obj.content); System.out.println(“첨부: " + obj.attachment); out.writeObject(obj); } catch (IOException ioe) { System.out.println("파일로 출력할 수 없습니다."); finally { out.close(); catch (Exception e) { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import java.io.*; class ObjectInputExample4 { public static void main(String args[]) { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream("output4.dat")); BBSItem obj = (BBSItem) in.readObject(); System.out.println(“전체게시물의 수: " + obj.itemNum); System.out.println(“글쓴이: " + obj.writer); System.out.println(“패스워드: " + obj.passwd); System.out.println(“제목: " + obj.title); System.out.println(“내용: " + obj.content); System.out.println(“첨부: " + obj.attachment); } catch (FileNotFoundException fnfe) { System.out.println("파일이 존재하지 않습니다."); catch (EOFException eofe) { System.out.println(“끝"); catch (IOException ioe) { System.out.println("파일을 읽을 수 없습니다."); catch (ClassNotFoundException cnfe) { System.out.println("해당 클래스가 존재하지 않습니다."); finally { in.close(); catch (Exception e) { 에러 메시지
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 불가능한 필드 타입 [예제 17-7] 게시물 클래스의 객체를 직렬화하고 역직렬화하는 프로그램 BBSItem 객체를 직렬화하는 프로그램 BBSItem 객체를 역직렬화하는 프로그램 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.io.*; class ObjectOutputExample4 { public static void main(String args[]) { ObjectOutputStream out = null; try { out = new ObjectOutputStream(new FileOutputStream("output4.dat")); BBSItem obj = new BBSItem(“이석영”, “moonlight”, “자료 파일입니다.”, “첨부 파일을 참고하십시오.”); obj.addAttachment(“모카자바 500g 15500원”); System.out.println(“전체게시물의 수: " + obj.itemNum); System.out.println(“글쓴이: " + obj.writer); System.out.println(“패스워드: " + obj.passwd); System.out.println(“제목: " + obj.title); System.out.println(“내용: " + obj.content); System.out.println(“첨부: " + obj.attachment); out.writeObject(obj); } catch (IOException ioe) { System.out.println("파일로 출력할 수 없습니다."); finally { out.close(); catch (Exception e) { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import java.io.*; class ObjectInputExample4 { public static void main(String args[]) { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream("output4.dat")); BBSItem obj = (BBSItem) in.readObject(); System.out.println(“전체게시물의 수: " + obj.itemNum); System.out.println(“글쓴이: " + obj.writer); System.out.println(“패스워드: " + obj.passwd); System.out.println(“제목: " + obj.title); System.out.println(“내용: " + obj.content); System.out.println(“첨부: " + obj.attachment); } catch (FileNotFoundException fnfe) { System.out.println("파일이 존재하지 않습니다."); catch (EOFException eofe) { System.out.println(“끝"); catch (IOException ioe) { System.out.println("파일을 읽을 수 없습니다."); catch (ClassNotFoundException cnfe) { System.out.println("해당 클래스가 존재하지 않습니다."); finally { in.close(); catch (Exception e) { 제대로 출력됨
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 • 다음과 같은 희소 배열(sparse array)를 직렬화하는 경우
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 • 디폴트 직렬화 메커니즘을 사용하면 비효율적입니다.
객체의 직렬화 02. 직렬화 가능 클래스의 선언 방법 직렬화 메소드와 역직렬화 메소드 • 더 효율적인 방법은?
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 [예제 17-8] 2차원 배열 필드를 포함하는 클래스 이런 클래스가 있다고 가정합시다. 1 2 3 4 5 6 7 import java.io.*; class DistrChart implements Serializable { int arr[][]; DistrChart() { arr = new int[10][10]; } 이 배열이 희소 배열로 사용된다고 가정합시다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 • 직렬화 메소드의 작성 방법 1) writeObject라는 이름의 메소드를 선언합니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 • 직렬화 메소드의 작성 방법 2) writeObject 메소드 안에 원하는 필드만 직렬화하는 명령문을 써넣습니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 • 역직렬화 메소드의 작성 방법 1) readObject라는 이름의 메소드를 선언합니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 • 역직렬화 메소드의 작성 방법 2) readObject 메소드 안에 데이터를 읽어서 필드에 대입하는 명령문을 써넣습니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 [예제 17-9] 직렬화/역직렬화 메소드를 포함하는 직렬화 가능 클래스의 예 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.io.*; class DistrChart implements Serializable { int arr[][]; DistrChart() { arr = new int[10][10]; } private void writeObject(ObjectOutputStream out) throws IOException { for (int row = 0; row < arr.length; row++) { for (int col = 0; col < arr[0].length; col++) { if (arr[row][col] != 0) { out.writeInt(row); out.writeInt(col); out.writeInt(arr[row][col]); private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { arr = new int[10][10]; try { while (true) { int row = in.readInt(); int col = in.readInt(); int data = in.readInt(); arr[row][col] = data; catch (EOFException e) { 직렬화 메소드 역직렬화 메소드
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 [예제 17-10] DistrChart 객체를 직렬화하고 역직렬화하는 프로그램 DistrChart 객체를 직렬화하는 프로그램 DistrChart 객체를 역직렬화하는 프로그램 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.io.*; class ObjectOutputExample5 { public static void main(String args[]) { ObjectOutputStream out = null; try { out = new ObjectOutputStream(new FileOutputStream("output5.dat")); DistrChart obj = new DistrChart(); obj.arr[0][1] = 2; obj.arr[4][5] = 5; obj.arr[6][1] = 2; obj.arr[7][7] = 7; obj.arr[8][4] = 21; out.writeObject(obj); } catch (IOException ioe) { System.out.println("파일로 출력할 수 없습니다."); finally { out.close(); catch (Exception e) { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import java.io.*; class ObjectInputExample5 { public static void main(String args[]) { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream("output5.dat")); DistrChart obj = (DistrChart) in.readObject(); for (int row = 0; row < obj.arr.length; row++) { for (int col = 0; col < obj.arr[0].length; col++) { System.out.printf("%3d", obj.arr[row][col]); } System.out.println(); catch (FileNotFoundException fnfe) { System.out.println("파일이 존재하지 않습니다."); catch (EOFException eofe) { System.out.println("끝"); catch (IOException ioe) { System.out.println("파일을 읽을 수 없습니다."); catch (ClassNotFoundException cnfe) { System.out.println("해당 클래스가 존재하지 않습니다."); finally { in.close(); catch (Exception e) {
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 메소드와 역직렬화 메소드 • 디폴트 직렬화 메커니즘과의 차이점 확인 [예제 17-8, 예제 17-10을 실행했을 때의 결과] 디폴트 직렬화 메커니즘이 생성하는 파일의 크기 [예제 17-9, 예제 17-10을 실행했을 때의 결과] [예제 17-9]의 직렬화 메소드가 생성하는 파일의 크기
객체의 직렬화 02. 직렬화 가능 클래스의 선언 방법 직렬화 메소드와 역직렬화 메소드 • 직렬화 메소드가 호출되는 메커니즘
객체의 직렬화 02. 직렬화 가능 클래스의 선언 방법 직렬화 메소드와 역직렬화 메소드 • 역직렬화 메소드가 호출되는 메커니즘
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 [예제 17-11] 상품 정보 클래스와 서브클래스들 상품 정보 클래스 1 2 3 4 5 6 7 8 9 10 class GoodsInfo { String code; // 상품코드 String name; // 상품명 int price; // 가격 GoodsInfo(String name, String code, int price) { this.name = name; this.code = code; this.price = price; } 상 속 상 속 이런 클래스들이 있다고 가정합시다. 의류 정보 클래스 도서 정보 클래스 1 2 3 4 5 6 7 8 9 10 class ClothingInfo extends GoodsInfo { String color; // 색상 char size; // 사이즈: L M S ClothingInfo(String name, String code, int price, String color, char size) { super(name, code, price); this.color = color; this.size = size; } 1 2 3 4 5 6 7 8 9 10 class BookInfo extends GoodsInfo { String writer; // 글쓴이 int page; // 페이지 수 BookInfo(String name, String code, int price, String writer, int page) { super(name, code, price); this.writer = writer; this.page = page; }
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 [예제 17-12] java.io.Serializable 인터페이스를 구현하는 도서 정보 클래스 1 2 3 4 5 6 7 8 9 class BookInfo extends GoodsInfo implements java.io.Serializable { String writer; // 글쓴이 int page; // 페이지 수 BookInfo(String name, String code, int price, String writer, int page) { super(name, code, price); this.writer = writer; this.page = page; } 이렇게 선언하는 것만으로 충분할까요?
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 [예제 17-13] BookInfo 객체를 직렬화하고 역직렬화하는 프로그램 BookInfo 객체를 직렬화하는 프로그램 BookInfo 객체를 역직렬화하는 프로그램 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.io.*; class ObjectOutputExample6 { public static void main(String args[]) { ObjectOutputStream out = null; try { out = new ObjectOutputStream(new FileOutputStream("output6.dat")); BookInfo obj = new BookInfo("80801", "반지의 제왕", 20000, "톨킨", 636); System.out.println("상품코드: " + obj.code); System.out.println("상품명: " + obj.name); System.out.println("가격: " + obj.price); System.out.println("지은이:" + obj.writer); System.out.println("페이지수:" + obj.page); out.writeObject(obj); } catch (IOException ioe) { System.out.println(ioe.getMessage()); finally { out.close(); catch (Exception e) { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import java.io.*; class ObjectInputExample6 { public static void main(String args[]) { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream("output6.dat")); BookInfo obj = (BookInfo) in.readObject(); System.out.println("상품코드: " + obj.code); System.out.println("상품명: " + obj.name); System.out.println("가격: " + obj.price); System.out.println("지은이:" + obj.writer); System.out.println("페이지수:" + obj.page); } catch (FileNotFoundException fnfe) { System.out.println("파일이 존재하지 않습니다."); catch (EOFException eofe) { System.out.println("끝"); catch (IOException ioe) { System.out.println(ioe.getMessage()); catch (ClassNotFoundException cnfe) { System.out.println("해당 클래스가 존재하지 않습니다."); finally { in.close(); catch (Exception e) { 역직렬화할 때 이런 에러가 발생합니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 • 객체를 역직렬화할 때 호출되는 생성자 직렬화 가능 클래스의 생성자 호출 메커니즘 때문입니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 [예제 17-14] no-arg constructor를 추가한 GoodsInfo 클래스 1 2 3 4 5 6 7 8 9 10 11 12 class GoodsInfo { String code; // 상품코드 String name; // 상품명 int price; // 가격 GoodsInfo() { } GoodsInfo(String name, String code, int price) { this.name = name; this.code = code; this.price = price; 이 클래스를 가지고 직렬화/역직렬화 프로그램을 실행하면 에러가 발생하지 않을 것입니다. no-arg constructor 하지만 아직도 몇몇 필드의 값이 제대로 출력되지 않았습니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 • 클래스의 상속 관계와 직렬화 되는 필드 상속과 관련된 직렬화/역직렬화 메커니즘 때문입니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 • 앞 예제에서 직렬화/역직렬화 프로그램을 실행했을 때 일어난 일
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 [예제 17-15] writeObject, readObject 메소드를 추가한 BookInfo 클래스 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.io.*; class BookInfo extends GoodsInfo implements Serializable { String writer; // 글쓴이 int page; // 페이지 수 BookInfo(String name, String code, int price, String writer, int page) { super(name, code, price); this.writer = writer; this.page = page; } private void writeObject(ObjectOutputStream out) throws IOException { out.writeUTF(code); out.writeUTF(name); out.writeInt(price); out.writeUTF(writer); out.writeInt(page); private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { code = in.readUTF(); name = in.readUTF(); price = in.readInt(); writer = in.readUTF(); page = in.readInt(); 이 클래스를 가지고 실행하면 직렬화/역직렬화가 정상적으로 될 것입니다. 슈퍼클래스의 필드를 직렬화하는 명령문 이 클래스의 필드를 직렬화하는 명령문 슈퍼클래스의 필드를 역직렬화하는 명령문 이 클래스의 필드를 역직렬화하는 명령문
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 • 클래스 자신의 디폴트 직렬화 메커니즘을 호출하는 방법 이렇게 하면 앞 예제의 직렬화 메소드를 더 간단히 만들 수 있습니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 • 클래스 자신의 디폴트 역직렬화 메커니즘을 호출하는 방법 앞 예제의 역직렬화 메소드도 더 간단히 만들 수 있습니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 다른 클래스를 상속받는 직렬화 가능 클래스 [예제 17-16] 디폴트 직렬화/역직렬화 메소드를 호출하는 BookInfo 클래스 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.io.*; class BookInfo extends GoodsInfo implements Serializable { String writer; // 글쓴이 int page; // 페이지 수 BookInfo(String name, String code, int price, String writer, int page) { super(name, code, price); this.writer = writer; this.page = page; } private void writeObject(ObjectOutputStream out) throws IOException { out.writeUTF(code); out.writeUTF(name); out.writeInt(price); out.defaultWriteObject(); private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { code = in.readUTF(); name = in.readUTF(); price = in.readInt(); in.defaultReadObject(); 수정된 직렬화/역직렬화 메소드입니다. 실행 결과는 앞에서와 동일합니다. 슈퍼클래스의 필드를 직렬화하는 명령문 이 클래스의 필드를 직렬화하는 메소드 호출문 슈퍼클래스의 필드를 역직렬화하는 명령문 이 클래스의 필드를 역직렬화하는 메소드 호출문
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 버전 관리 [예제 17-17] 직렬화 가능한 사각형 클래스 1 2 3 4 5 6 7 class Rectangle implements java.io.Serializable { int width, height; Rectangle(int width, int height) { this.width = width; this.height = height; } 이런 클래스가 있다고 가정합시다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 버전 관리 [예제 17-18] Rectangle 클래스의 객체를 직렬화하고 역직렬화하는 프로그램 Rectangle 객체를 직렬화하는 프로그램 Rectangle 객체를 역직렬화하는 프로그램 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.io.*; class ObjectOutputExample7 { public static void main(String args[]) { ObjectOutputStream out = null; try { out = new ObjectOutputStream(new FileOutputStream("output7.dat")); Rectangle obj = new Rectangle(100, 200); System.out.println(“넓이: " + obj.width); System.out.println(“높이: " + obj.height); out.writeObject(obj); } catch (IOException ioe) { System.out.println(ioe.getMessage()); finally { out.close(); catch (Exception e) { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.io.*; class ObjectInputExample7 { public static void main(String args[]) { ObjectInputStream in = null; try { in = new ObjectInputStream(new FileInputStream("output7.dat")); Rectangle obj = (Rectangle) in.readObject(); System.out.println(“넓이: " + obj.width); System.out.println(“높이: " + obj.height); } catch (FileNotFoundException fnfe) { System.out.println("파일이 존재하지 않습니다."); catch (EOFException eofe) { System.out.println("끝"); catch (IOException ioe) { System.out.println(ioe.getMessage()); catch (ClassNotFoundException cnfe) { System.out.println("해당 클래스가 존재하지 않습니다."); finally { in.close(); catch (Exception e) { 같은 Rectangle 클래스를 가지고 실행하면 정상적인 실행 결과가 나옵니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 버전 관리 [예제 17-19] 새로운 메소드가 추가된 사각형 클래스 1 2 3 4 5 6 7 8 9 10 class Rectangle implements java.io.Serializable { int width, height; Rectangle(int width, int height) { this.width = width; this.height = height; } int getArea() { return width * height; Rectangle 클래스를 이렇게 수정한 후에 역직렬화 프로그램을 실행하면 어떻게 될까요? 추가된 메소드
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 버전 관리 [예제 17-20] 버전 번호를 포함하는 사각형 클래스 (1) 1 2 3 4 5 6 7 8 class Rectangle implements java.io.Serializable { static final long serialVersionUID = 100; int width, height; Rectangle(int width, int height) { this.width = width; this.height = height; } 버전 번호 이렇게 버전 번호를 붙이면 문제를 해결할 수 있습니다.
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 버전 관리 [예제 17-21] 버전 번호를 포함하는 사각형 클래스 (2) 1 2 3 4 5 6 7 8 9 10 11 class Rectangle implements java.io.Serializable { static final long serialVersionUID = 100; int width, height; Rectangle(int width, int height) { this.width = width; this.height = height; } int getArea() { return width * height; 버전 번호 클래스를 수정한 후에도 똑같은 버전 번호를 유지해야 합니다. 추가된 메소드 [예제 17-20]의 Rectangle 클래스를 가지고 직렬화 프로그램을 실행했을 때 [예제 17-21]의 Rectangle 클래스를 가지고 역직렬화 프로그램을 실행했을 때
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 버전 관리 • 버전 번호의 충돌을 최소화하는 방법 1) 직렬화 가능 클래스를 작성합니다. 2) 직렬화 가능 클래스를 컴파일합니다. 3) 컴파일한 디렉토리에서 serialver 명령을 실행하면 버전 번호가 생성됩니다. 버전 번호
02. 직렬화 가능 클래스의 선언 방법 객체의 직렬화 직렬화 가능 클래스의 버전 관리 [예제 17-22] serialver 명령이 생성한 버전 번호를 붙인 사각형 클래스 1 2 3 4 5 6 7 8 9 10 11 class Rectangle implements java.io.Serializable { static final long serialVersionUID = 1292117344561223774L; int width, height; Rectangle(int width, int height) { this.width = width; this.height = height; } int getArea() { return width * height; 1 2 3 4 5 6 7 8 class Rectangle implements java.io.Serializable { static final long serialVersionUID = 1292117344561223774L; int width, height; Rectangle(int width, int height) { this.width = width; this.height = height; } 버전 번호 원래의 Rectangle 클래스를 가지고 직렬화 프로그램을 실행했을 때 getArea 메소드가 추가된 Rectangle 클래스를 가지고 역직렬화 프로그램을 실행했을 때