본문 바로가기

개발자이야기/JAVA이야기

Serializable 과 transient 의미와 사용법

반응형

출처 ==> http://hyeonstorage.tistory.com/254


Serializable 과 transient


(1) Serializable


데이터를 파일에 쓰거나, 네트워크를 타고 다른 곳에 전송할 때는 데이터를 바이트 단위로 분해하여 순차적으로 보내야 한다. 이것을 직렬화(Serialization)라고 한다.


기본 자료형(boolean, char, byte, short, int ,long, float, double)은 정해진 바이트의 변수이기 때문에 바이트 단위로 분해하여 전송한 후 다시 조립하는데 문제가 없다.


하지만 객체의 크기는 가변적이며, 객체를 구성하는 자료형들의 종류와 수에 따라 객체의 크기는 다양하게 바뀔 수 있다. 이런 객체를 직렬화 하기 위해서 Serializable 인터페이스를 구현하게 된다.


[JAVA] 객체 직렬화 ObjectInputStream / ObjectOutputStream


* 직렬화가 가능한 객체의 조건


① 기본형 타입(boolean, char, byte, short, int, long, float, double)은 직렬화가 가능

② Serializable 인터페이스를 구현한 객체여야 한다. (Vector 클래스는 Serializable 인터페이스구현)

③ 해당 객체의 멤버들 중에 Serializable 인터페이스가 구현되지 않은게 존재하면 안된다.

④ transient 가 사용된 멤버는 전송되지 않는다. (보안 변수 : null 전송)


객체 직렬화는 객체에 implements Serializable 만 선언해 주면 된다.


(2) transient


하지만, 객체의 데이터 중 일부의 데이터는(패스워드와 같은 보안) 여러가지 이유로 전송을 하고 싶지 않을 수 있다. 이러한 변수는 직렬화에서 제외해야 되며, 이를 위해서 변수에 transient를 선언한다.


또한, 직렬화 조건 중 객체의 멤버들 중에 Serializable 인터페이스 구현되지 않은 객체가 있으면, 직렬화 할 수 없다.(NonSerializableException) 직렬화 해야 되는 객체 안의 객체 중 Serializable 인터페이스가 구현되지 않으면서 전송하지 않아도 되는 객체 앞에는 transient 를 선언해준다. 그러면 직렬화 대상에서 제외되므로 해당 객체는 직렬화가 가능해진다.


* Serializable 과 transient 사용 예제


UserClass.java

 


import java.io.Serializable;

// 직렬화 한다.
public class UserClass implements Serializable{
	
	private static final long serialVersionUID = 4220461820168818967L;
	
	String name;
	
	// age 비 전송
	transient int age;
	
	// NonSerializable 클래스
	NonSerializableClass nonSerializable;
	
	
	public UserClass() {
		
	}
	
	public UserClass(String name, int age){
		
		this.name = name;
		this.age = age;
		
		this.nonSerializable = new NonSerializableClass(false);
		
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	

	public NonSerializableClass getNonSerializable() {
		return nonSerializable;
	}

	public void setNonSerializable(NonSerializableClass nonSerializable) {
		this.nonSerializable = nonSerializable;
	}

	@Override
	public String toString() {
		return "UserClass [name=" + name + ", age=" + age
				+ ", nonSerializable=" + nonSerializable + "]";
	}
	
}


접기


 


public class NonSerializableClass {
	
	boolean serializable;
	
	public NonSerializableClass(){
	
		this.serializable = false;
	}
	
	public NonSerializableClass(boolean serializable){
		this.serializable = serializable;
	}

}


접기


접기


 

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ObjectStream {
	
	public static void main(String[] args){
		
		// ObjectOutputStream 을 이용한 객체 파일 저장
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
	
		// UserClass 에 이름과 나이를 입력하여 객체를 3개 생성한다.
		UserClass us1 = new UserClass("하이언", 30);
		UserClass us2 = new UserClass("스티브", 33);
		UserClass us3 = new UserClass("제이슨", 27);
		
		
		try{
			
			// object.dat 파일의 객체 아웃풋스트림을 생성한다.
			fos = new FileOutputStream("object.dat");
			oos = new ObjectOutputStream(fos);
			
			// 해당 파일에 3개의 객체를 순차적으로 쓴다
			oos.writeObject(us1);
			oos.writeObject(us2);
			oos.writeObject(us3);
			
			// object.dat 파일에 3개의 객체 쓰기 완료.
			System.out.println("객체를 저장했습니다.");
		
		}catch(Exception e){
			
			e.printStackTrace();
		
		}finally{
			
			// 스트림을 닫아준다.
			if(fos != null) try{fos.close();}catch(IOException e){}
			if(oos != null) try{oos.close();}catch(IOException e){}	
		}
		
		
		// 파일로 부터 객체 데이터 읽어온다.
		FileInputStream fis = null;
		ObjectInputStream ois = null;
		
		try{
			
			// object.dat 파일로 부터 객체를 읽어오는 스트림을 생성한다.
			fis = new FileInputStream("object.dat");
			ois = new ObjectInputStream(fis);
			
			// ObjectInputStream으로 부터 객체 하나씩 읽어서 출력한다.
			// (UserClass) 로 형변환을 작성해야 한다.
			// System.out.println 으로 객체의 구현된 toString() 함수를 호출한다.
			System.out.println( (UserClass)ois.readObject());
			System.out.println( (UserClass)ois.readObject());
			System.out.println( (UserClass)ois.readObject());


		}catch(Exception e){
			e.printStackTrace();
		}finally{
			
			// 스트림을 닫아준다.
			if(fis != null) try{fis.close();}catch(IOException e){}
			if(ois != null) try{ois.close();}catch(IOException e){}
		}
		
		
	}

}


접기



- UserClass.java 의 변수를 보면 transient int age; 로 age 변수는 직렬화에서 제외했다.

- NonSerializableClass 객체는 Serializable 인터페이스를 구현하지 않은 클래스이다.

- 따라서 UserClass.java 로 직렬화를 시도하면, 위와 같이 NonSerializableClass Exception이 발생한다.


- 위의 문제를 해결하기 위해서는 NonSerializableClass.java 에 Serializable 인터페이스를 구현하여 직렬화를 할 수 있게 하는 방법과

- NonSerializableClass 를 전송하지 않아도 되면, 또는 않아야 한다면 transient 를 앞에 붙여주는 것이다.

- 그러면 NonSerializableClass 객체는 직렬화 대상에서 제외되면서 UserClass 가 정상적으로 직렬화되어 처리될 것이다.


* NonSerializableClass 객체 선언 앞에 transient 선언 결과


 

import java.io.Serializable;

// 직렬화 한다.
public class UserClass implements Serializable{
	
	private static final long serialVersionUID = 4220461820168818967L;
	
	String name;
	
	// age 비 전송
	transient int age;
	
	// NonSerializable 클래스
	transient NonSerializableClass nonSerializable;
	
	
	public UserClass() {
		
	}
	
	public UserClass(String name, int age){
		
		this.name = name;
		this.age = age;
		
		this.nonSerializable = new NonSerializableClass(false);
		
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	

	public NonSerializableClass getNonSerializable() {
		return nonSerializable;
	}

	public void setNonSerializable(NonSerializableClass nonSerializable) {
		this.nonSerializable = nonSerializable;
	}

	@Override
	public String toString() {
		return "UserClass [name=" + name + ", age=" + age
				+ ", nonSerializable=" + nonSerializable + "]";
	}
	
}



- 객체가 정상적으로 직렬화되어 전송되고, 가져와 출력되는 것을 볼 수 있다.

- 당연히 transient가 붙은 age 변수와 nonSerializable 은 직렬화 되지 않기에 데이터가 없다.


 ObjectStream.zip

반응형

'개발자이야기 > JAVA이야기' 카테고리의 다른 글

poi 관련  (0) 2014.07.15
serialVersionUID 생성하기  (0) 2014.07.01
gson for json library (google) - user guide  (0) 2014.06.27
java file read/write 잘정리된 곳  (0) 2014.03.21
파일 인코딩 관련  (0) 2014.01.27