如何序列化 Java 类的静态数据成员?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1008023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to serialize static data members of a Java class?
提问by Maddy.Shik
When we serialize objects, static members are not serialized, but if we need to do so, is there any way out?
当我们序列化对象时,静态成员并没有被序列化,但是如果我们需要这样做,有什么出路吗?
采纳答案by Kathy Van Stone
The first question is why you need to serialize the static members?
第一个问题是为什么需要序列化静态成员?
Static members are associated with the class, not the instances, so it does not make sense to include them when serializing an instance.
静态成员与类相关联,而不是与实例相关联,因此在序列化实例时包含它们是没有意义的。
The first solution is to make those members not static. Or, if those members are the same in the original class and the target class (same class, but possibly different runtime environments), don't serialize them at all.
第一个解决方案是使这些成员不是静态的。或者,如果这些成员在原始类和目标类中相同(相同的类,但可能不同的运行时环境),则根本不要序列化它们。
I have a few thoughts on how one could send across static members, but I first need to see the use case, as in all cases that means updating the target class, and I haven't found a good reason to do so.
我对如何跨静态成员发送有一些想法,但我首先需要查看用例,因为在所有情况下都意味着更新目标类,但我还没有找到这样做的充分理由。
回答by Thorbj?rn Ravn Andersen
Static members belong to the class, not to the individual objects.
静态成员属于类,而不属于单个对象。
You should reconsider your data structure.
您应该重新考虑您的数据结构。
回答by Nick Holt
You can control serialization by implementing:
您可以通过实现来控制序列化:
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
There's a full description of serialization http://java.sun.com/developer/technicalArticles/Programming/serialization/.
有关于序列化的完整描述http://java.sun.com/developer/technicalArticles/Programming/serialization/。
As other answers have said, it doesn't really make sense to serialize statics as it's the object not the class you're serializing and needing to do so smells like you've got other issues with your code to me.
正如其他答案所说,序列化静态数据并没有真正意义,因为它是对象而不是您正在序列化的类,并且需要这样做,这让我感觉您的代码有其他问题。
回答by Bill K
Good answers and comments--don't do it. But how?
好的答案和评论——不要这样做。但是如何?
Chances are you would be best off creating an object to hold all your "Statics". That object should probably have any static methods from your class as well.
很有可能你最好创建一个对象来保存你所有的“静态”。该对象可能也应该具有您的类中的任何静态方法。
Every instance of your class can hold this other class--or if you really have to you can make it a singleton that any member can access.
你的类的每个实例都可以保存这个另一个类——或者如果你真的需要你可以让它成为任何成员都可以访问的单例。
After you do this refactor, you will find that it should have been done this way all along. You may even find that some of your previous design constraints that were bothering you at a subconsicionce level have vanished.
做完这个重构之后,你会发现它一直都应该是这样做的。您甚至可能会发现,一些以前在潜意识层面困扰您的设计约束已经消失了。
You'll probably find that this solution also solves other Serialization problems you hadn't even noticed yet.
您可能会发现此解决方案还解决了您甚至还没有注意到的其他序列化问题。
回答by Vladimir Dyuzhev
Folks, static doesn't mean IMMUTABLE. For instance, I may want to serialize the whole state of the computation (yes, including static fields -- counters, etc) to resume later, after JVM and/or host computer restarted.
伙计们,静态并不意味着不变。例如,我可能想序列化整个计算状态(是的,包括静态字段——计数器等),以便稍后在 JVM 和/或主机重新启动后恢复。
The right answer to that, as already said, is to use Externalizable, not Serializable, interface. Then you have a complete control on what and how you externalize.
如前所述,正确的答案是使用 Externalizable 而不是 Serializable 接口。然后,您可以完全控制外化的内容和方式。
回答by naresh
Yes, we can serialize the static variables. But we can write our own writeObject()
and readObject()
. I think this can solve the problem.
是的,我们可以序列化静态变量。但是我们可以编写自己的writeObject()
和readObject()
. 我认为这可以解决问题。
回答by G Kumar
To have compact implementation, implement readObject & writeObject in your class call defaultReadObject & defaultWriteObject methods within those methods which handles normal serialization and then proceed with serializing & de-serializing whatever additional fields you need.
为了获得紧凑的实现,在你的类中实现 readObject 和 writeObject 调用 defaultReadObject 和 defaultWriteObject 方法在处理正常序列化的那些方法中,然后继续序列化和反序列化你需要的任何附加字段。
Regards, GK
问候, GK
回答by Adam
This is serialization for the static field: newBookingNumber.
这是静态字段的序列化: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();
}
}
回答by bobjandal
You can do this without having to manually update your class every time you simply change a field. You may want to do this if you want to have the ease of static members for access to settings in an application, but would also like to save those settings. In this case, you would also want to have the option to apply them at whim, not load by default as the other solutions here necessitate, since they are static. This allows for rollback of settings for obvious reasons.
您无需在每次更改字段时手动更新类即可执行此操作。如果您想使用静态成员轻松访问应用程序中的设置,但又想保存这些设置,您可能想要这样做。在这种情况下,您还希望可以选择随心所欲地应用它们,而不是默认加载,因为这里需要其他解决方案,因为它们是静态的。这允许出于显而易见的原因回滚设置。
Basically, use the field methods to get all the members in the class, then map the full names of these fields to the contents. The full name is required since Field is not serializable itself. Serialize this mapping, and reinstate it to get the saved settings.
基本上,使用字段方法获取类中的所有成员,然后将这些字段的全名映射到内容。由于 Field 本身不可序列化,因此需要全名。序列化此映射,并恢复它以获取保存的设置。
The second part of the puzzle is the apply() type of function. This goes thru the mapping, and applies what it can to the static class.
谜题的第二部分是 apply() 类型的函数。这通过映射,并将其应用于静态类。
You must also ensure that the contents of the static members are themselves serializable.
您还必须确保静态成员的内容本身是可序列化的。
As can hopefully be seen from this example class, the static members can easily be saved and returned. I'll leave it up to the implementer to worry about UIDs of classes, safeguards etc. isSameAs() is used for unit testing. AppSettings is the class that contains all the static fields that you wish to serialize.
从这个示例类中可以看出,静态成员可以很容易地保存和返回。我将把它留给实现者来担心类的 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);
}
}
}
}
}
This is my first post - go easy on me :P~
这是我的第一篇文章 - 放轻松:P~