java - 小于 ObjectOutputStream 基元的基元数组

标签 java arrays memory serialization memory-management

我有一个函数,它接受一个对象并将其转换为字节数组:

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

最佳答案

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 个字节。

对于其他对象(例如装箱基元),它使用更多空间,因为它必须存储更多元信息。它必须存储对象的类型,并且对于每个成员,它必须存储相同的信息 - 所以它有点递归地进行。

如果您确实想详细了解发生了什么,我建议您阅读source code ObjectOutputStream

关于java - 小于 ObjectOutputStream 基元的基元数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35636186/

相关文章:

c++ - vector <X*>* 与 vector <X>*

android - 内存转储Android中的应用程序

java - 使用定界符将字符串数组转换为 int

java - 在 Java 中使用 stream.sorted() 对列表进行排序

javascript - 如何使用 React 正确更新数组中的状态?

c++ - 如何编写一个模板函数,它接受一个数组和一个指定数组大小的 int

java - 请放心验证 JSON 正文是否包含列表中的所有字符串

java - 不能从静态上下文中引用内部类,但前提是外部类是通用的

java - 如何在不重置Java的情况下绘制多个对象

事件查看器中的 ASP.NET 2.0 System.AccessViolationException