1

假设我创建了一个 B 类的实例,它有一个静态变量 x,在 B 类声明中赋值为 3。在 main() 方法中,我这样做:

B b = new B();
b.x = 7; //allowed to use an instance to set the static member value

在此之后, b 被序列化然后反序列化。然后,出现以下行:

System.out.println ("static: " + b.x);

有什么价值?7个还是3个?

我知道静态变量没有序列化,但是,因为整个类只有一个静态成员的副本,并且值设置为 7,是否应该在反序列化实例后保留它?

4

4 回答 4

8

这是发生的事情:

  1. 静态初始化器将值设置为 3。
  2. 实例构造函数将值设置为 7。
  3. 序列化不知道静态变量,它被忽略。
  4. 反序列化不知道静态变量并被忽略。
  5. 如果程序一直在运行,或者程序被关闭并重新启动,则值仍然是 7(来自构造函数中发生的更改),静态初始化程序会将其设置为 3 并且反序列化不会更改它。

如果你想要你描述的逻辑,你需要添加另一个静态变量来计算创建的实例数,并用你的自定义逻辑覆盖writeObjectand方法。readObject

于 2009-12-18T16:15:22.710 回答
7

如果您在同一个 JVM 实例中反序列化它,您的第二个片段将返回 7。这是因为 bx 的值设置为 7。这没有改变,因为B 的实例已被序列化和反序列化。

如果你序列化对象,关闭 JVM,启动一个新的 JVM,然后反序列化对象(除了静态初始化之外不设置 bx),bx 的值将是 3。

于 2009-12-18T16:14:52.540 回答
1

使用以下代码对内存中的流进行序列化和反序列化以及对象:

package com.example.serialization;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; 
import junit.framework.TestCase;


public class SerializationTest extends TestCase {
    public void testStaticValueAfterSerialization() {
       B b = new B();
       b.x = 7; //allowed to use an instance to set the static member value

       B deserializedB = copyObject(b);
       assertEquals("b.x should be 7 after serialization", 7, deserializedB.x);
    }

    private <T extends Serializable> T copyObject(final T source) {
        if (source == null)
                throw new IllegalArgumentException("source is null");
        final T copy;
        try {
            copy = serializationClone(source);
            } catch (Exception e) {
                // (optional) die gloriously!
            throw new AssertionError("Error copying: " + source, e);
        }    
            return copy;
    }

    private <T extends Serializable> T serializationClone(final T source)
        throws IOException, ClassNotFoundException {
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    ObjectOutputStream outputStream = new ObjectOutputStream(byteStream);

            // 1. serialize the object to the in-memory output stream
        outputStream.writeObject(source);

        ObjectInputStream inputStream = new ObjectInputStream(
                new ByteArrayInputStream(byteStream.toByteArray()));

        // 2. deserialize the object from the in-memory input stream
        @SuppressWarnings("unchecked")
            final T copy = (T) inputStream.readObject();

        return copy; // NOPMD : v. supra
    }
}

创建该类后,使用 JUnit 运行程序运行它,看看测试是否通过!如果您愿意,可以在一个测试用例中将结果写入文件。然后在另一个测试用例中,从文件中读取结果!

于 2009-12-18T17:05:07.367 回答
0

由于静态初始化程序只运行一次,因此值为7.

于 2009-12-18T16:16:11.413 回答