在 Java 序列化機制中,final 修飾的基本型別欄位往往被視為不可變常數,但在反序列化過程中,其行為可能出乎意料。這道經典題目探討的正是這一點。
package Nov2016;
import java.io.Serializable;
public class Ques1111 implements Serializable {
private static final long serialVersionUID = 1L;
public final int num = 123;
}
將 Ques1111 物件序列化並寫入磁碟。隨後,直接修改磁碟上的序列化資料,將 num 欄位的值從 123 改為 321。當再次反序列化該資料時,得到的物件中 num 的值將是多少?
Java 序列化規範規定,final 基本型別欄位(如 int、long 等)在序列化時會寫入其數值。反序列化時,JVM 會透過反射機制直接賦值給該欄位,而不會呼叫建構子。因此,若序列化資料流中的位元組被竄改,反序列化出來的物件將攜帶被修改後的值。
答案:321
final 物件參考,反序列化同樣會重新綁定參考,但物件本身的不可變性取決於該物件類別的設計。serialVersionUID,確保跨版本反序列化的一致性,避免 InvalidClassException。這道題為後續探討「序列化代理模式」與「writeReplace/readResolve」鋪墊,掌握 final 欄位反序列化語意是理解進階序列化技巧的基石。