2016-02-25 4 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 байт как вы наблюдаете в своем эксперименте.

Для других объектов, таких как примитивы в штучной упаковке, он использует больше места, поскольку он должен хранить гораздо больше метаинформации. Он должен хранить их тип объекта, и для каждого члена он должен хранить одну и ту же информацию - так что он идет рекурсивно.

Если вы действительно хотите понять, что происходит подробно, я рекомендую прочитать source code из ObjectOutputStream.

1

Это связано с тем, что Java использует другую кодировку для массивов, которая более эффективна. Если вы сериализуете Byte, он пишет, что у вас есть объект (который вы можете ссылаться позже, чтобы он записывал идентификатор), который имеет класс java.lang.Byte (который снова имеет идентификатор), который имеет родительский класс java.lang.Number (также с идентификатором) , который не имеет полей, байт имеет одно поле, которое называется «значение» (которое является строкой с идентификатором), а значение байта использует только один байт.

Байт [] имеет внутреннее имя [B, у которого нет родительских полей, поэтому он намного короче.

Смежные вопросы