질문의 역사:
Java는 처음부터 Serializable 인터페이스를 통해 객체 직렬화 메커니즘을 지원합니다. 객체의 상태를 저장해야 할 때가 있지만, 모든 필드를 직렬화할 필요는 없습니다. 예를 들어, 필드가 보안에 민감하거나 동적으로 계산될 수 있기 때문입니다. 이러한 경우를 위해 transient 수정자가 고안되었습니다.
문제:
객체를 전체적으로 직렬화할 경우, 개별 필드의 특성을 고려하지 않으면 비공식적이거나 직렬화에 취약한 데이터가 유출될 수 있습니다. 또한, 무거운 필드나 임시 필드(예: 스레드, 데이터베이스 연결)의 직렬화 및 역직렬화는 오류를 발생시키거나 성능 저하를 초래할 수 있습니다.
해결책:
객체를 저장할 때 직렬화되지 않아야 할 필드에 대해 transient 수정자를 사용하십시오. 이러한 필드는 직렬화 메커니즘에 의해 단순히 무시되며, 역직렬화될 때 기본값(예: 참조 유형의 경우 null, 숫자의 경우 0)을 갖습니다.
코드 예:
import java.io.*; class User implements Serializable { private String username; private transient String password; // 직렬화되지 않습니다! public User(String username, String password) { this.username = username; this.password = password; } }
주요 특징:
정적 필드는 transient일 수 있습니까?
답변: 필드를 static transient로 선언할 수 있지만 의미가 없습니다. 정적 필드는 본래 클래스에 속하고 객체에는 속하지 않기 때문에 직렬화되지 않기 때문입니다.
transient 필드의 직렬화에 대해 완전한 제어를 할 수 있습니까?
답변: 네, private void writeObject(ObjectOutputStream out) 및 private void readObject(ObjectInputStream in) 메서드를 구현함으로써 필요 시 transient 필드를 수동으로 직렬화할 수 있습니다.
코드 예:
private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); // out.writeObject(password); // transient 필드를 명시적으로 직렬화하려면 }
final transient 필드는 역직렬화 후 어떻게 됩니까?
답변: final transient 필드도 기본값(보통 0 또는 null)을 갖게 되지만, 특별한 조작 없이 변경할 수 없으므로 종종 버그를 초래합니다.
DatabaseConnection이라는 transient 필드를 가진 객체를 직렬화했습니다. 역직렬화 후 이 연결의 메서드를 호출하려고 했더니 NullPointerException이 발생했습니다.
장점:
단점:
transient 비밀번호가 있는 User 객체를 직렬화했습니다. 역직렬화 중 readObject에서 사용자에게 비밀번호를 요청하거나 연결을 복구했습니다.
장점:
단점: