如何序列化Java类的静态数据成员?
当我们序列化对象时,静态成员不会被序列化,但是如果我们需要这样做,有什么办法吗?第一个问题是为什么需要序列化静态成员 静态成员与类相关联,而不是与实例相关联,因此在序列化实例时包含它们是没有意义的 第一个解决方案是使这些成员不是静态的。或者,如果这些成员在原始类和目标类中相同(相同的类,但可能不同的运行时环境),则根本不序列化它们如何序列化Java类的静态数据成员?,java,serialization,static-members,Java,Serialization,Static Members,当我们序列化对象时,静态成员不会被序列化,但是如果我们需要这样做,有什么办法吗?第一个问题是为什么需要序列化静态成员 静态成员与类相关联,而不是与实例相关联,因此在序列化实例时包含它们是没有意义的 第一个解决方案是使这些成员不是静态的。或者,如果这些成员在原始类和目标类中相同(相同的类,但可能不同的运行时环境),则根本不序列化它们 我对如何跨静态成员发送有一些想法,但我首先需要查看用例,因为在所有情况下,这意味着更新目标类,我还没有找到这样做的好理由。静态成员属于类,而不是单个对象 您应该重新考
我对如何跨静态成员发送有一些想法,但我首先需要查看用例,因为在所有情况下,这意味着更新目标类,我还没有找到这样做的好理由。静态成员属于类,而不是单个对象
您应该重新考虑您的数据结构。您可以通过实现以下功能来控制序列化:
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
这里有对序列化的完整描述
正如其他答案所说,序列化静态并没有真正的意义,因为它是对象而不是您正在序列化的类,并且需要这样做,我觉得您的代码有其他问题。好的答案和注释--不要这样做。但是怎么做呢
您最好创建一个对象来保存所有的“静态”。该对象可能也应该具有您的类中的任何静态方法
您的类的每个实例都可以容纳另一个类——或者,如果您确实需要,您可以使它成为任何成员都可以访问的单例
在您完成这个重构之后,您会发现它应该一直以这种方式完成。您甚至可能会发现,以前在潜意识层面困扰您的一些设计约束已经消失
您可能会发现,此解决方案还解决了您尚未注意到的其他序列化问题。各位,静态并不意味着不可变。例如,我可能希望序列化整个计算状态(是的,包括静态字段——计数器等),以便在JVM和/或主机重新启动后恢复
如前所述,正确的答案是使用可外部化而不是可序列化的接口。然后您就可以完全控制外部化的内容和方式。是的,我们可以序列化静态变量。但是我们可以编写自己的
writeObject()
和readObject()
。我认为这可以解决问题。要实现紧凑的实现,请在类中实现readObject和writeObject,在处理正常序列化的方法中调用defaultReadObject和defaultWriteObject方法,然后继续序列化和反序列化您需要的任何其他字段
问候,,
GK这是静态字段的序列化:newBookingNumber
class Booking implements Serializable
{
/**
* Generated serial version ID.
*/
private static final long serialVersionUID = 5316748056989930874L;
// To hold new booking number.
private static int newBookingNumber = 0;
// The booking number.
private int bookingNumber;
/*
* Default serializable fields of a class are defined to be
* the non-transient and non-static fields. So, we have to
* write and read the static field separately.
*/
private void writeObject(ObjectOutputStream oos)
throws IOException
{
oos.defaultWriteObject();
oos.writeObject(new Integer(newBookingNumber));
}
private void readObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException
{
ois.defaultReadObject();
newBookingNumber = (Integer)ois.readObject();
}
}
您可以做到这一点,而无需在每次更改字段时手动更新类。 如果您想让静态成员轻松访问应用程序中的设置,但也希望保存这些设置,则可能需要执行此操作。 在这种情况下,您还希望能够随心所欲地应用它们,而不是像这里的其他解决方案那样默认加载,因为它们是静态的。这允许出于明显的原因回滚设置 基本上,使用field方法获取类中的所有成员,然后将这些字段的全名映射到内容。全名是必需的,因为字段本身不可序列化。序列化此映射,并将其恢复以获取保存的设置 谜题的第二部分是函数的apply()类型。这将遍历映射,并将其应用于静态类 您还必须确保静态成员的内容本身是可序列化的 从这个示例类中可以看到,静态成员可以很容易地保存和返回。我将让实现者来担心类的UID、安全措施等。isSameAs()用于单元测试。AppSettings是包含要序列化的所有静态字段的类
public class AppSettingsReflectorSaver implements Serializable {
HashMap<String, Object> genericNamesAndContents = new HashMap<String, Object>();
private AppSettingsReflectorSaver() {
}
static AppSettingsReflectorSaver createAppSettingsSaver() {
AppSettingsReflectorSaver ret = new AppSettingsReflectorSaver();
ret.copyAppSettings();
return ret;
}
private void copyAppSettings() {
Field[] fields = AppSettings.class.getFields();
for (Field field : fields) {
mapContentsForSerialization(field);
}
}
private void mapContentsForSerialization(Field field) {
try {
Object fieldContents = field.get(AppSettings.class);
genericNamesAndContents.put(field.toGenericString(), fieldContents);
} catch (IllegalArgumentException ex) {
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex);
}
}
boolean isSameAs(AppSettingsReflectorSaver now) {
for( String thisKey : genericNamesAndContents.keySet()){
boolean otherHasThisKey = now.genericNamesAndContents.containsKey(thisKey);
Object thisObject = genericNamesAndContents.get(thisKey);
Object otherObject = now.genericNamesAndContents.get(thisKey);
boolean otherHasThisValue = thisObject.equals(otherObject);
if (!otherHasThisKey || !otherHasThisValue){
return false;
}
}
return true;
}
void applySavedSettingsToStatic() {
Field[] fields = AppSettings.class.getFields();
for (Field field : fields) {
if (!genericNamesAndContents.containsKey(field.toGenericString())){
continue;
}
Object content = genericNamesAndContents.get(field.toGenericString() );
try {
field.set(AppSettings.class, content);
} catch (IllegalArgumentException ex) {
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
公共类AppSettingsReflectorSaver实现可序列化{
HashMap genericNamesAndContents=新HashMap();
私有应用程序设置反射保护程序(){
}
静态AppSettingsReflectorSaver createAppSettingsSaver(){
AppSettingsReflectorSaver ret=新的AppSettingsReflectorSaver();
ret.copyAppSettings();
返回ret;
}
私有void copyAppSettings(){
Field[]fields=AppSettings.class.getFields();
用于(字段:字段){
mapContentsForSerialization(字段);
}
}
私有void映射内容序列化(字段){
试一试{
对象fieldContents=field.get(AppSettings.class);
genericNamesAndContents.put(field.toGenericString(),fieldContents);
}捕获(IllegalArgumentException ex){
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE,null,ex);
}捕获(非法访问例外){
Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE,null,ex);
}
}
布尔值isSameAs(AppSettingsReflectorSaver现在){
for(字符串thisKey:genericNamesAndContents.keySet()){
布尔值otherHasThisKey=now.genericNamesAndContents.containsKey(thisKey);
Object thisObject=genericNamesAndContents.get(thisKey);
Object otherObject=now.genericNamesAndContents.get(thisKey);
布尔值otherHasThisValue=thisObject.equals(otherObject);
如果(!otherHasThisKey | |!otherHasThisValue){
返回false;
}
}
返回true;
}
无效applySavedSettingsToStatic(){
Field[]fields=AppSettings.class.getFields();
用于(字段:字段){
if(!genericNamesAndContents.containsKey(field.toGenericString())){
继续;
}
对象内容