2017-01-10 1 views
-1

나는 성공적으로 내 사용자 정의 개체를 직렬화했지만 내가 역 직렬화 할 때이 문제가 발생합니다 :의 역 직렬화 된 오브젝트 필드는 null이

- 사용자 정의 개체가

- 모든 필드는 NULL이다 NULL이 아니다

내가 알고 직렬화 파일을 읽었으므로 정상적으로 내 사용자 정의 객체를 직렬화했습니다. 여기

내 코드입니다 :

여기
public class Preferences implements Serializable { 

private static Preferences instance; 
public static final long serialVersionUID = 3358037972944864859L; 
public String accessToken; 

protected Object readResolve() { 
    return getInstance(); 
} 

private Preferences() { 

} 

private synchronized static void synchronize() { 
    if(instance == null) { 
     instance = new Preferences(); 
    } 
} 

public static Preferences getInstance() { 
    if(instance == null) { 
     Preferences.synchronize(); 
    } 

    return instance; 
} 

public void save(File file) { 
    try { 
     FileOutputStream fos = new FileOutputStream(file); 
     ObjectOutputStream out = new ObjectOutputStream(fos); 

     Preferences tempInstance = Preferences.getInstance(); 

     out.writeObject(tempInstance); 
     out.close(); 
     fos.close(); 
    }catch(IOException e) { 
     e.printStackTrace(); 
    } 
} 

public void load(File file) { 
    try { 
     FileInputStream fis = new FileInputStream(file); 
     ObjectInputStream in = new ObjectInputStream(fis); 

     if(file.length() > 0) { 
      Preferences tempInstance = (Preferences) in.readObject(); 

      Log.e("", String.valueOf(tempInstance == null)); //prints FALSE 
      Log.e("", String.valueOf(tempInstance.accessToken == null)); //prints TRUE 
     } 

     in.close(); 
     fis.close(); 
    }catch(IOException | ClassNotFoundException e) { 
     e.printStackTrace(); 
    } 
} 
} 

내 테스트 코드 : 문제가 무엇인지에

public class CustomActivity extends AppCompatActivity { 

private File dir = new File(Environment.getExternalStorageDirectory(), ".app"); 
private File backup = new File(dir, "backup.ser"); 

@Override 
protected void onCreate(@Nullable Bundle savedInstanceState) { 
    Log.e("APPLICATION", "START"); 

    super.onCreate(savedInstanceState); 

    if(this instanceof ActivityLogin) { 
     if(!dir.exists()) { 
      dir.mkdirs(); 
     } 

     Preferences.getInstance().load(backup); 
    } 
} 

@Override 
protected void onUserLeaveHint() { 
    super.onUserLeaveHint(); 

    try { 
     backup.createNewFile(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    Preferences.getInstance().save(backup); 

    Log.e("APPLICATION", "STOP"); 
} 

}

어떤 생각이?

+0

읽은 개체로 아무 것도하지 않습니다. 로드 메소드는 정적이어야하며 비 직렬화 된 인스턴스를 리턴해야합니다. 'instance'와'this'는 서로 관련이없는 두 개의 서로 다른 객체입니다. –

+0

load()가 끝난 후에 인스턴스 객체로 무언가를하고 있지만 load() 인스턴스는 null이 아니며 모든 필드가 null입니다. 내 편집을 참조하십시오. @JBNizet – jelic98

+0

오류를 재현하는 완전한 최소 예를 게시하십시오. 우리는 당신이 무엇을 직렬화하고 비 직렬화하는지 알지 못합니다. –

답변

3

당신은 클래스에서이 방법이 있습니다

protected Object readResolve() { 
    return getInstance(); 
} 

이 직렬화 메커니즘을 알려줍니다 : 당신이 기본 인스턴스를 직렬화 할 때마다, getInstance()에 의해 반환 된 하나 교체하십시오. 따라서 load() 호출과 Preferences의 인스턴스에 null accessToken이있는 경우 동일한 객체이므로 deserialized 환경 설정도 null accessToken을 갖습니다.

은 (당신이 로그인 할 때 안드로이드에서 사용하는 어떤 또는) 로깅 문에

System.out.println(tempInstance == this); 

을 추가하면 볼 수 있습니다.

+0

감사합니다. 그 방법을 제거해야합니까? – jelic98

+1

예. 그러나 나는 또한 끔찍한 싱글 톤 안티 패턴 사용을 중단 할 것입니다. 로드 메소드를 정적으로 만들고 비 직렬화 된 환경 설정을 리턴하고 변수에 저장하십시오. –

+0

나는 load 메소드를 정적으로 만들고 Preferences 객체를 반환하게했다. instance filed를 설정하고 load()를 매개 변수로 전달하는 setInstance()를 작성하면 어떨까요? – jelic98