实际上我想了解序列化的概念以及瞬态和局部变量与serialversionuid以及序列化实际发生方式有何关联的方式?
答案 0 :(得分:1)
基本上没有。 serialVersionUID
通常用于确定类的哪个版本彼此兼容(通常在集群环境中),如果您希望在任何上下文中支持应用程序的多个版本,则可以将此字段增加到防止以前版本的应用程序炸毁新字段。
标有transient
的字段未序列化。
最后,当多个线程可以访问字段时,volatile
用于防止编译器进行不安全的优化。例如,double checked-locking。来自维基百科,
从J2SE 5.0开始,此问题已得到修复。 volatile关键字现在确保多个线程正确处理单例实例。这个新的习语在[4]中描述:
// Works with acquire/release semantics for volatile // Broken under Java 1.4 and earlier semantics for volatile class Foo { private volatile Helper helper; public Helper getHelper() { Helper result = helper; if (result == null) { synchronized(this) { result = helper; if (result == null) { helper = result = new Helper(); } } } return result; } // other functions and members... }
答案 1 :(得分:1)
Java中的transient关键字用于指示不应序列化字段。 来自Java语言规范,Java SE 7 Edition,第8.3.1.3节。瞬态字段:
变量可以标记为瞬态,表示它们不是对象持久状态的一部分。 局部变量可以序列化
令人惊讶的是,如果在类中将静态成员字段声明为瞬态或最终成员字段为瞬态,则java编译器不会抱怨。这些应该是编译时错误。因为"瞬态"假设一个对象的一部分状态在每个实例中都在变化,它不能是静态的或最终的
序列化运行时将每个可序列化类与版本号相关联,称为serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已为该对象加载了兼容的类关于序列化。如果接收者已经为具有与相应发送者类的serialVersionUID不同的serialVersionUID的对象加载了类,则反序列化将导致InvalidClassException。可序列化类可以通过声明名为" serialVersionUID"的字段来显式声明其自己的serialVersionUID。必须是static,final和long类型: ANY-ACCESS-MODIFIER静态最终长serialVersionUID = 42L; 如果可序列化类未显式声明serialVersionUID,则序列化运行时将基于类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。但是,强烈建议所有可序列化类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节高度敏感,这些细节可能因编译器实现而异,因此在反序列化期间可能导致意外的InvalidClassExceptions。因此,为了保证跨不同java编译器实现的一致的serialVersionUID值,可序列化类必须声明显式的serialVersionUID值。强烈建议显式serialVersionUID声明尽可能使用private修饰符,因为此类声明仅适用于立即声明的类 - serialVersionUID字段不适用于继承成员。
Java文档说:
"默认的serialVersionUID计算对类详细信息非常敏感,这些详细信息可能因编译器实现而异,因此在反序列化期间会导致意外的InvalidClassExceptions"。
您必须声明serialVersionUID,因为它为我们提供了更多控制权。