2013-02-20 6 views
0
package p1; 

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.ObjectStreamException; 
import java.io.Serializable; 


public class SerializationCheck { 
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { 
     SingletonCompanyCEO s1 = SingletonCompanyCEO.getSingleObject(); 
     SingletonCompanyCEO s2 = SingletonCompanyCEO.getSingleObject(); 
     System.out.println("s1==s2:"+(s1==s2)); 

     ObjectOutputStream obs = new ObjectOutputStream(new FileOutputStream("file.txt")); 
     obs.writeObject(s1); 

     //first read from file 
     ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file.txt")); 
     SingletonCompanyCEO ceo = (SingletonCompanyCEO)ois.readObject(); 

     //second read from file 
     ois = new ObjectInputStream(new FileInputStream("file.txt")); 
     SingletonCompanyCEO ceo1 = (SingletonCompanyCEO)ois.readObject(); 

     System.out.println("ceo==ceo1:"+(ceo==ceo1)+" (read from file ie. de-serialized)"); 
     System.out.println(ceo1); 


    } 
} 

class SingletonCompanyCEO implements Serializable 
{ 
    public void setName(String name){ 
     this.name = name; 
    } 
    public Object readResolve() throws ObjectStreamException { 
     return singleObject; 
    } 
    private static final long serialVersionUID = 1L; 
    private transient int age = 55; // age should set to zero by default as age is transient. But it is not happening, any reason? 
    private String name ="Amit"; 
    float salary = 0f; 

    private static SingletonCompanyCEO singleObject; 
    private SingletonCompanyCEO() 
    { 
     if(singleObject!=null) 
     { 
      throw new IllegalStateException(); 
     } 
    } 
    public static SingletonCompanyCEO getSingleObject() 
    { 
     if(singleObject==null) 
     { 
      singleObject = new SingletonCompanyCEO(); 
     } 
     return singleObject; 
    } 
    public String toString() 
    { 
     return name+" is CEO of the company and his age is "+ 
     age+"(here 'age' is transient variable and did not set to zero while serialization)"; 
    } 
} 

이 코드를 복사하여 이클립스 편집기에 붙여 넣으십시오. 'age'transient 변수가 직렬화 중에 기본적으로 0으로 설정되지 않은 이유는 무엇입니까?
직렬화에서는 직렬화 중에 transient 및 static 변수가 0 (또는 기본값)으로 설정됩니다.
역 직렬화 후 age = 0 대신 age = 55이 발생합니다.
JLS에서 이유가 있어야합니다. 이게 뭐야?transient 변수의 상태가 싱글 톤 객체에 저장되는 이유는 무엇입니까?

답변

1

SingletonCompanyCEO 객체가 직렬화 복원되는 모든 시간, ObjectInputStream와에서 얻은 모든 정보가 삭제되고 대신 singleObject 때문에 당신의 readResolve 방법, 반환됩니다. singleObject 자체는 비 직렬화가 아니라 생성자를 사용하여 만든 인스턴스이므로 나이가 55입니다.

0
private transient int age = 55; 

선언시 값을 정의하면이 값이 우선합니다.

1

getSingleObject 메서드를 사용하여 고정 SingletonCompanyCEO 개체를 제공하고 있습니다. 따라서 다음 참조 변수 SingletonCompanyCEO, 즉 s1, s2은 동일한 SingletonCompanyCEO 개체를 공유합니다.

age = 55; 
name ="Amit"; 
salary = 0f; 

을하지만 당신은 또한 당신이 s1s2 참조하고있는에 동일한 개체를 반환하는 SingletonCompanyCEO 클래스 readResolve 방법을 재정의이 고유의 목적을 위해 당신은 필드에 값을 다음했다. 따라서 클래스 JVM을 비 직렬화하면 변수 ceoceo1s1s2이 참조하는 동일한 객체를 참조합니다. 그래서 기본적으로 직렬화와 비 직렬화 후에 하나의 객체 인 SingletonCompanyCEO을 가지고 있습니다. 이것이 age55으로 인쇄되는 이유입니다.

UPDATE : 객체가 읽은 후

  1. JVM이 "file.txt를"에서 개체를 읽 여기
    readResolve 후 코드에 포함 된 단계는 코드에서 제거된다 JVM은 readResolve 메소드를 SingletonCompanyCEO 클래스로 찾습니다. JVM이 readResolve을 찾지 못하고 새 객체ceo으로 반환합니다.
  2. JVM이 다시 "file.txt"에서 개체를 읽습니다. 객체를 읽은 후 JVM은 readResolve 메소드를 클래스 SingletonCompanyCEO에서 찾습니다. JVM이 readResolve을 찾지 못하고 새 객체ceo1으로 역 직렬화에 의해 반환됩니다.

은 따라서 두 직렬화 후에는 SingletonCompanyCEO의 두 가지 새로운 개체가.
=> ceo == ceo1은 false를 반환합니다.
참고 : 새로 생성 된 객체 값이 모두 age 인 경우 JLS에서 지정한대로 0이됩니다.

UPDATE2
직렬화가있는 동안 당신은 코드의 writeobject 부분을 언급하고 다음 단계에 따라 파일 (file.txt)을 이미 사용하여 기존의 클래스를 직렬화 발생하는 경우 :

  1. JVM 파일에서 개체를 읽고 ObjectInputStream를 사용합니다. 객체를 읽은 후 JVM은 메서드를 SingletonCompanyCEO 클래스에서 찾습니다. JVM은 해당 객체만을 클래스에 정의 된 readResolve() 메소드가 반환하는 변수에 반환합니다.
  2. JVM이 readResolve() 메소드를 찾습니다. 메서드에서 은 null이며, 아직 getSingleObject() 메서드는 호출되지 않았습니다. 그리고 귀하의 정보를 위해, 클래스의 생성자는 또한 deserialization 동안 호출되지 않습니다. 그렇지 않으면 constructor에서 수행 한 것처럼 IllegalstateException을 던졌습니다.
  3. readResolve()null이므로 JVM도 null을 반환합니다. 계속되는 ceo1ceo2은 모두 null입니다.
+0

동의합니다. 위의 코드를 실행 한 다음 s1 및 s2 참조 생성을위한 코드를 제거하고 객체 쓰기 코드도 제거합니다. 이제 우리는 객체를 포함하는 파일을 직렬화했습니다. 제거한 후 파일을 읽는 코드 만 있습니다. 이제는 객체가 생성되지 않는 것을 발견했습니다. 'null'은 파일을 읽은 후 반환됩니다. 이제 다시 readResolve()를 제거해보십시오. 그러면 객체가 생성되고 단일성 객체가 아닌 것을 알 수 있습니다. 이게 뭐야? – AmitG

+1

@AmitG : 내 업데이트를 참조하십시오. –

+0

확인. 동의하다. 그러나 readResolve() 메소드를 유지하면 객체가 파일에서 'null'이됩니다. 어때? JVM 당 인스턴스 만 가져올 수 있도록 Singleton 객체를 deserialize하는 방법은 무엇입니까? readResolve()를 유지하면 두 개의 객체가 만들어지고 readResolve()를 유지하지 않으면 객체가 만들어지지 않습니다. – AmitG