2016-02-25 54 views
1

原始较小我有它接受一个对象,并把它变成一个字节数组的函数:阵列的比原始对的ObjectOutputStream

public static byte[] serialize(Object obj) throws IOException { 
    try(ByteArrayOutputStream b = new ByteArrayOutputStream()){ 
     try(ObjectOutputStream o = new ObjectOutputStream(b)){ 
      o.writeObject(obj); 
     } 
     return b.toByteArray(); 
    } 
} 

当我使用上的原始类型此功能,输出最终被大于相同基元的单一数组。

public static void main (String[] args) throws java.lang.Exception 
{ 
    System.out.format("byte single: %d, array: %d\n", 
      serialize((byte) 1).length, serialize(new byte[]{1}).length); 

    System.out.format("short single: %d, array: %d\n", 
      serialize((short) 1).length, serialize(new short[]{1}).length); 

    System.out.format("int  single: %d, array: %d\n", 
      serialize((int) 1).length, serialize(new int[]{1}).length); 

    System.out.format("float single: %d, array: %d\n", 
      serialize((float) 1).length, serialize(new float[]{1}).length); 

    System.out.format("double single: %d, array: %d\n", 
      serialize((double) 1).length, serialize(new double[]{1}).length); 

} 

这将产生:

byte single: 75, array: 28 
short single: 77, array: 29 
int  single: 81, array: 31 
float single: 79, array: 31 
double single: 84, array: 35 

这到底是怎么回事?为什么数组更小?这是一个Ideone for the issue

回答

1

ObjectOutputStream正在处理原始数组不同于其他对象。你是不是序列化的原语,但反对,因为他们得到这样的序列化之前int盒装成为Integer

对于数组,ObjectOutputStream刚刚写入以下内容(我用double为例)

1 byte // to mark it as array 
22 bytes // for the class description 
4 bytes // the length of the array 
8 bytes // for the double (would be array.length * 8) is you have more elements 

这使得35个字节正如你在实验中观察到的那样。

对于其他对象 - 像盒装原语 - 它使用更多的空间,因为它必须存储更多的元信息。它必须存储它们对象的类型,并且对于每个成员它必须存储相同的信息 - 所以它有点递归。

如果您真的想详细了解正在进行的操作,建议您阅读ObjectOutputStreamsource code

1

这是因为Java对数组使用不同的编码效率更高。如果你序列化了一个Byte,它会写入你有一个对象(你可能会在后面提到,所以它会记录一个id),它有一个类java.lang.Byte(它也有一个id),它有一个父类java.lang.Number(也带有一个id) ,它没有字段,字节有一个字段被称为“值”(这是一个带有id的字符串),字节的值只使用一个字节。

一个字节[]的内部名称为[B,它没有字段父项,所以它更短。