개발자 미니민의 개발스터디

[JAVA] 자바 - 객체 직렬화(ObjectStream, Object Serialization)

by mini_min
[JAVA]
자바 - 객체 직렬화(ObjectStream, Object Serialization)

✔️ ObjectInputStream

ObjectOutputStream  클래스에 의해 파일이 저장되거나 네트워크로 전달된 객체의 직렬화를 해제하는 기능을 한다.

파일이나 네트워크로 받은 직렬화 된 데이터를 다시 원래 데이터로 복원하는 역할!!

= readObject() 메소드를 사용해 복원한다. 이후 ✨원래 데이터로 캐스팅✨하여 사용한다.

 

📓 스트림으로 읽을 수 있는 객체

- Serializable 인터페이스 or Externalizable 인터페이스를 구현한 클래스의 객체 

 

public static void main(String[] args) {
		String pathname = "object.txt";
		
		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pathname))){
			
			@SuppressWarnings("unchecked")
			Hashtable<String, String> ht = (Hashtable<String, String>)ois.readObject();
			
			Iterator<String> it = ht.keySet().iterator();
			while(it.hasNext()) {
				String key = it.next();
				String value = ht.get(key);
				
				System.out.println(key + "->" + value);
				
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
💡 readObject() 메소드를 사용할 때, 원래 데이터로 캐스팅해준다.
= (Hashtable<String, String>)ois.readObject();

 

 

✔️ ObjectOutputStream

객체를 출력하는 기능을 제공하는 클래스로 출력 스트림에 출력하기 전에 직렬화를 수행한다.

파일이나 네트워크로 데이터를 전송하기 위해 직렬화를 수행하며 이때, writeObject() 메소드를 사용

 

📓 스트림으로 저장할 수 있는 객체

- Serializable 인터페이스를 구현한 클래스의 객체

 

public static void main(String[] args) {
		
		
		//오브젝트 스트림은 직렬화 되어야한다.
		Hashtable<String, String> ht = new Hashtable<>();
		ht.put("자바", "프로그래밍");
		ht.put("HTML", "웹 프로그래밍");
		ht.put("오라클", "데이터베이스");
		
		String pathname = "object.txt";
		
		
		//ObjectOutputStream : 직렬화된 객체를 저장할 수 있는 스트림이다. 선두에 클래스명이 저장됨
		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(pathname))) {
			
			oos.writeObject(ht);
			
			System.out.println("저장완료");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		

	}

 

 

 

✔️ 객체 직렬화란?

직렬화는 자바 시스템 내부에서 사용되는 객체 또는 데이터를 자바 외부에서도 사용할 수 있도록 바이트 단위로 변환하는 것이다.

 

📓 직렬화가 가능한 자료형 및 객체

- 기본형 타입들 (char, byte, int 등..)

- Serializable 인터페이스를 구현한 클래스의 객체

- transient 가 사용된 멤버변수 , static 멤버변수, 메소드는 직렬화 대상에서 제외된다.

 

✨ 역 직렬화

: 직렬화된 바이트 단위의 데이터를 다시 원래 데이터로 복원하는 것

 

 

✔️ 객체 직렬화 방법

1) 먼저, 객체가 직렬화되도록 Serializable 인터페이스를 구현해야한다.

2) 해당 인터페이스가 자바 가상 머신에 객체 직렬화가 필요함을 알린다.

3) 따로 구현할 메소드가 없고, 단지 Serializable 인터페이스만 implements 해주면 된다.

💡 직렬화가 가능한 객체만 ObjectoutputStream 으로 저장 가능

 

✨ transient

: 직렬화 대상에서 제외할 멤버 변수는 해당 키워드 붙여 제외한다.

: transient 키워드가 붙은 멤버 변수가 복원되면 숫자변수는 0, 객체는 null 로 설정된다.

 

public static void main(String[] args) {
		String pathname = "demo.txt";
		
		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(pathname))) {
			
			// 주소 저장한거라서 의미 없다. 
			// 주소가 아니라 주소 안에 내용을 직접적으로 가져와야함. 그래서 직렬화가 필요하다. 
			oos.writeObject(new UserVO("가가가", "010-1111-1111", 20));;
			oos.writeObject(new UserVO("나나나", "010-2222-2222", 20));;
			oos.writeObject(new UserVO("다다다", "010-3333-3333", 20));;
			
			System.out.println("파일 저장 완료!");
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		

		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pathname))) {
			System.out.println("\n파일 내용 ... ");
			
			while(true) {
				UserVO vo = (UserVO)ois.readObject();		// 직렬화된 데이터를 읽어 복원 
				System.out.println(vo.getName()+ "," + vo.getTel() + "," + vo.getAge());
				
			}

		} catch (EOFException e) {
			// ObjectInputStream 에서 더이상 읽을 자료가 없는 경우 발생하는 예외이다. 
		} catch (FileNotFoundException e) {
			System.out.println("등록된 파일이 없습니다.");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

// Serializable : 객체를 직렬화 가능하도록 설정 작업
// 직렬화 대상에서 제외되는 것 : 메소드, static 변수, transient 변수, 

class UserVO implements Serializable {

	private static final long serialVersionUID = 1L;
	
	private String name;
	private transient String tel;  // 전화번호는 직렬화에서 제외. 읽어오면 null
	private int age;
	
	public UserVO() {
	}
	
	public UserVO(String name, String tel, int age) {
		this.name = name;
		this.tel = tel;
		this.age = age;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
}
💡 Serializable : 객체를 직렬화 가능하도록 설정 작업
직렬화 대상에서 제외되는 것 : 메소드, static 변수, transient 변수

💡 EOFException : ObjectInputStream 에서 더이상 읽을 자료가 없는 경우 발생하는 예외이다. 

 

 

✔️ serialVersionUID 필드

직렬화에 사용되는 고유 아이디!!

선언하지 않으면 JVM 이 디폴트로 자동 생성해준다. serialVersionUID 는 역 직렬화 해서 읽을 때 캐스팅한 클래스와 역 직렬화한 serialVersionUID 가 맞는지 확인하기 위해 사용한다.

✨ 꼭 선언하지 않아도 되지만, serialVersionUID  계산은 세부 사항을 민감하게 반영해서 선언해주는게 좋음 🥺

= InvalidClassException 을 유발 할 수 있다.

 

 

 

 

 

 

블로그의 정보

개발자 미니민의 개발로그

mini_min

활동하기