Имеется объект с большим количество полей типа байт и массив байт, как можно с наиболее меньшим объемом кода сохранить только сами значения полей объекта в массив байт? наподобие как это например делается на с++: char* pBuffer = (char*)&some_object;
используя сериализацию помимо самих значений полей записываются также метаданные, что меня не устраивает
объект логически представляет собой структуру(как в c++ структура), то есть данные, которые удобно заполнять обращаясь к полям. и мне нужно сохранять в массив байт только сами значений полей пример объекта:
class AnyClass
{
private byte field1=0;
private byte field2=1;
private byte[] field3={0,1,2,3};
.
.
.
private byte field40=40;
}
Если скорость не имеет значения, в ход обычно пускают рефлексию, если скорость критична, используют сериализацию без рефлексии. Есть куча уроков как осуществить сереализацию через тот же класс java.io.Serializable.
Сам процесс такой сериализации можно собственноручно пощупать на примере 2 методов:
public interface IMySerialized {
byte[] serialize(); // метод должен будет собрать у класса сериализованные данные
void deserialize(byte[] data); // метод, который по сериализованным данным должен будет заполнить поля класса
}
public class Test implements IMySerialized {
private byte a; // наши поля
private byte b;
public byte[] serialize() {
return new byte[]{a,b}; // содержимое метода несёт чисто теоретический смысл
}
void deserialize(byte[] data) {
this.a = data[0]; // содержимое метода несёт чисто теоретический смысл
this.b = data[1];
}
}
Суть такой безрефлексийной сериализации в том, что вы сами реализуете алгоритм сбора всей информации с полей в методе serialize, и сами реализуете обратный алгоритм разбора данных и заполнения полей в методе deserialize. То есть, добавляя новое поле, оба этих метода увеличивают свой объём.
Тут всё изощрённее. Обычно, создаётся одна/две аннотации, которые дают нашему сериализатору понять что нужно сериализовать, а что можно пропускать. Обычно, проще считать что все поля являются сериализуемыми, поэтому, метки делают только ради исключений. Пример нашего тестового класса:
public class Test {
private byte a;
private byte b;
}
Далее, собирается обработчик-сериализатор. Суть обработчика - через рефлексию вытащить все поля, в случае необходимости, проверить их аннотации, и пропустить игнорируемые поля. Далее, собрать все данные полей в кучу.
public static <T> byte[] serialize(T obj) throws Exception {
List<Byte> result = new ArrayList<Byte>();
for(Field field : obj.getClass().getDeclaredFields()) { // перебираем все поля в классе
field.setAccessible(true); // если поле приватное, меняем доступ к нему
Object data = field.get(obj); // читаем значение из поля
if(data instanceof byte[]) {
for(byte b : (byte[])data){
result.add(b);
}
continue;
}
if(data instanceof Byte){
result.add((Byte)data);
continue;
}
}
byte[] array = new byte[result.size()];
for(int i = result.size()-1; i>=0; i--){
array[i]=result.get(i);
}
return array;
}
Аналогичным образом пишется обратная обработка - десереализация.
Пример использования такого кода:
Test test = new Test();
Test2 test2 = new Test2();
byte[] data1 = MyHandler.serialise(test);
byte[] data2 = MyHandler.serialise(test2);
Причём, если сериализатор написан грамотно, то в дальнейшем, ему не важно что сериализовать, он одинаково легко разберёт любой класс и выпотрошит все его поля.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Представим, что есть коллекция целочисельных значенийНапример, 1 5 8 3 0 15 7
Работаю над проектомПонадобилось растянуть навороченный Bootstrap 3 шаблон на React приложение