Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何序列化Java类的静态数据成员?_Java_Serialization_Static Members - Fatal编程技术网

如何序列化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())){
继续;
}
对象内容