我正在尝试比较2 byte[]
,这是同一对象的序列化结果:
byte[]
通过序列化对象创建1byte[]
序列化第一个,然后再次对其进行序列化。我不明白这两个数组有何不同。反序列化第一个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。
为什么会这样?
HashMap
源代码中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.
^
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句