我试图比较两个byte[],它们是同一个对象序列化的结果:
byte[]是通过序列化对象来创建的。byte[],然后再序列化它。我不明白这两个数组是如何不同的。反序列化第一个byte[]应该重构原始对象,而序列化该对象与序列化原始对象相同。因此,2 byte[]应该是相同的。然而,在某些情况下,它们显然是不同的。
我正在序列化的对象(State)包含另一个对象(MapWrapper)的列表,而该对象又包含一个集合。根据集合的不同,我从比较代码中得到不同的结果。
这是MCVE:
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 java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
public static void main(String[] args) {
State state = new State();
state.maps.add(new MapWrapper());
byte[] pBA = stateToByteArray(state);
State pC = byteArrayToState(pBA);
byte[] zero = stateToByteArray(pC);
System.out.println(Arrays.equals(pBA, zero)); // see output below
State pC2 = byteArrayToState(pBA);
byte[] zero2 = stateToByteArray(pC2);
System.out.println(Arrays.equals(zero2, zero)); // always true
}
public static byte[] stateToByteArray(State s) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static State byteArrayToState(byte[] bytes) {
ObjectInputStream ois;
try {
ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return (State) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
class State implements Serializable {
private static final long serialVersionUID = 1L;
List<MapWrapper> maps = new ArrayList<>();
}
class MapWrapper implements Serializable {
private static final long serialVersionUID = 1L;
// Different options, choose one!
// List<Integer> ints = new ArrayList<>(); true
// List<Integer> ints = new ArrayList<>(3); true
// Map<String, Integer> map = new HashMap<>(); true
// Map<String, Integer> map = new HashMap<>(2); false
}由于某些原因,如果MapWrapper包含一个HashMap (或LinkedHashMap),并且是用初始容量初始化的,那么序列化会给出一个与序列化反序列化不同的结果。
我添加了反序列化的第二次迭代,并与第一次进行了比较。他们总是平等的。这种差异仅在第一次迭代之后才会显示出来。
请注意,我必须创建一个MapWrapper并将其添加到State中的列表中,就像在main开始时所做的那样,从而导致这种情况。
据我所知,初始容量只是一个性能参数。使用默认的或指定的不应更改行为或功能。
我正在使用jdk1.8.0_25和Windows7。
这一切为什么要发生?
发布于 2016-07-28 11:57:18
readObject中的以下行和注释解释了两者之间的区别:
s.readInt(); // Read and ignore number of buckets实际上,查看字节的十六进制,差别在于数字2(配置的桶数)和数字16 (默认的桶数)。我没有检查过这个特定字节的意思,但是如果它是其他的东西,那将是一个巧合,因为这是唯一的区别。
<snip> 08 00 00 00 02 00 00 00 00 78 78 // Original
<snip> 08 00 00 00 10 00 00 00 00 78 78 // Deserialized+serialized.
^https://stackoverflow.com/questions/38635375
复制相似问题