JAVA (структуры)

Модератор: Модераторы разделов

Ответить
Аватара пользователя
devilr
Сообщения: 3667
ОС: Mandriva => Gentoo (~amd64)
Контактная информация:

JAVA

Сообщение devilr »

Возник вопрос, на который я, уже довольно давно, не могу найти ответа: как java-программисты работают данными, которые в языках, типа C, могут быть представлены простой структурой?
Понятно, что можно, например, сложить некие переменные в класс, а потом уже каким либо методом достать их оттуда и превратить в непрерывный байтовый массив. Это, если формировать массив из переменных. А обратно как?
Есть ли что-либо в JAVA подобное указателям и структурам? Ведь, вряд ли, я первый, кто столкнулся с этой проблемой.
Последний раз редактировалось devilr 26.06.2018 01:25, всего редактировалось 1 раз.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Эхо разума
Спасибо сказали:
Kopilov
Сообщения: 949
ОС: [K]Ubuntu, Debian

Re: JAVA

Сообщение Kopilov »

devilr писал(а):
26.06.2018 00:34
Понятно, что можно, например, сложить некие переменные в класс, а потом уже каким либо методом достать их оттуда и превратить в непрерывные байтовый массив.
Это называется «сериализация». Обратно — десериализация, соответственно. Если не нужна совместимость бинарного формата/протокола с другими языками и нет попыток выжать из Java производительности C/C++ — ObjectOutputStream и ObjectInputStream в помощь. Главное, чтобы в сериализуемом и десериализуемем классах совпадали все поля, а так же значения SerialVersionUID. Вот подстраиваться под существующие бинарные форматы уже сложнее.
Спасибо сказали:
Kopilov
Сообщения: 949
ОС: [K]Ubuntu, Debian

Re: JAVA

Сообщение Kopilov »

devilr писал(а):
26.06.2018 00:34
Ведь, вряд ли, я первый, кто столкнулся с этой проблемой.
Что именно стало для Вас проблемой? Указателей нет, только ссылки. И их как-то всегда хватало… А чем именно классы хуже структур?
Коллега сейчас пишет программу для аналитики с узкоспециализированной областью применения, пытаясь обогнать по скорости топовые in-memory СУБД в своём use case. Он недавно мечтал о «C-подобных структурах для Java», но не для функционала, а для дальнейшей оптимизации уже оптимизированного кода.
Спасибо сказали:
Kopilov
Сообщения: 949
ОС: [K]Ubuntu, Debian

Re: JAVA

Сообщение Kopilov »

Kopilov писал:
26.06.2018 00:55
А чем именно классы хуже структур?
Правильнее даже, наверно, «А чем именно объекты хуже структур?» — если необходимостью на каждый чих писать классы — понимаю Вас, меня (и не только) это тоже одно время терзало. И это одна из причин, почему в нашем департаменте внедрили язык Ceylon: там есть синтаксический сахар для кортежей (туплов), очень близкий к классическим структурам по синтаксису и удобный для быстрого прототипирования ПО, но памяти жрущий ещё больше, чем классы и объекты.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3667
ОС: Mandriva => Gentoo (~amd64)
Контактная информация:

Re: JAVA

Сообщение devilr »

Допустим, есть некая железяка, которая по некоторому интерфейсу шлёт пакеты, со структурой, подобной этой:

Код: Выделить всё

typedef struct HEADER
{
  uint16_t  prefix;
  uint8_t   addr; 
  uint8_t   cmd;
  uint16_t  len; 
  uint8_t   data[];
  uint16_t sum16;
} header_t;
И их надо обработать, по возможности, быстро. В си-подобных языках я бы просто делал указатель, типа

Код: Выделить всё

 HEADER *header = (HEADER *)data; 
и обращался с полями данных легко и просто. А здесь... ну, можно конечно, брать из потока последовательно 2 байта, потом 1, потом снова 1, потом 2 и т.д. и складывать их в определённый класс. Но это долго и муторно, особенно, если структура завтра поменяется. Ошибок можно понаделать 100500 штук.
Вот и интересно, как другие программисты такое делают?
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Эхо разума
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu
Контактная информация:

Re: JAVA

Сообщение serzh-z »

devilr писал(а):
26.06.2018 01:21
Вот и интересно, как другие программисты такое делают?
Было бы логичным предположить, что делают слой абстракции, использующий JNA/JNI, а критичный код пишут на C.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3667
ОС: Mandriva => Gentoo (~amd64)
Контактная информация:

Re: JAVA

Сообщение devilr »

serzh-z писал:
26.06.2018 01:33
devilr писал(а):
26.06.2018 01:21
Вот и интересно, как другие программисты такое делают?
Было бы логичным предположить, что делают слой абстракции, использующий JNA/JNI, а критичный код пишут на C.
Это понятно. Можно вообще на assembler.
Я больше про то, можно ли подобные "низкоуровневые" веши реализовать в рамках JAVA? Вдруг кто-то знает элегантное решение.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Эхо разума
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu
Контактная информация:

Re: JAVA

Сообщение serzh-z »

devilr писал(а):
26.06.2018 01:42
элегантное решение.
Што? Java и элегантность? Да вы шутник. =)
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3667
ОС: Mandriva => Gentoo (~amd64)
Контактная информация:

Re: JAVA

Сообщение devilr »

Не надо цепляться к словам. :)
Часто не мы определяем среду и язык программирования.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Эхо разума
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20790
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: JAVA

Сообщение Bizdelnick »

devilr писал(а):
26.06.2018 01:21
Допустим, есть некая железяка, которая по некоторому интерфейсу шлёт пакеты, со структурой, подобной этой:

Код: Выделить всё

typedef struct HEADER
{
  uint16_t  prefix;
  uint8_t   addr; 
  uint8_t   cmd;
  uint16_t  len; 
  uint8_t   data[];
  uint16_t sum16;
} header_t;
И их надо обработать, по возможности, быстро. В си-подобных языках я бы просто делал указатель, типа

Код: Выделить всё

 HEADER *header = (HEADER *)data; 
и обращался с полями данных легко и просто. А здесь... ну, можно конечно, брать из потока последовательно 2 байта, потом 1, потом снова 1, потом 2 и т.д. и складывать их в определённый класс. Но это долго и муторно, особенно, если структура завтра поменяется. Ошибок можно понаделать 100500 штук.
Вот и интересно, как другие программисты такое делают?
А вот ни фига это не легко и не просто даже в C. Железяка-то наверняка шлёт данные подряд, без выравнивания, а у Вас структура не packed. Не говоря о том, что Вы не учитываете порядок байт в пакете, так что такой код не будет переносимым.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Kopilov
Сообщения: 949
ОС: [K]Ubuntu, Debian

Re: JAVA

Сообщение Kopilov »

devilr писал(а):
26.06.2018 10:22
Часто не мы определяем среду и язык программирования.
И кто определил за Вас, что драйвер (а у Вас получается именно драйвер для аппаратного обеспечения, не так ли?) надо писать именно на Java?

:sarcasm: бинарные форматы и элегантность? Да вы шутники, сейчас почти везде JSON / XML [YAML / TOML].

Впрочем, нет: лично сейчас делаю через Java кластеризацию математических расчётов над большими массивами данных (де факто, надо выпилить платный кластеризатор, идущий в комплекте с MATLAB, заставить ноды бегать на бесплатном Runtime и связать их самостоятельно). Подумав, что делать с сериализацией, решил использовать встроенную в RMI бинарную, т.к. перевод больших числовых матриц в текст и обратно — лишний расход не только вычислительных ресурсов, но и трафика.

Подстраиваться под существующие форматы, как я уже говорил, не так легко. Возможно, поможет Externalizable, но лично я этим не пользовался.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3667
ОС: Mandriva => Gentoo (~amd64)
Контактная информация:

Re: JAVA

Сообщение devilr »

Bizdelnick писал:
26.06.2018 10:46
А вот ни фига это не легко и не просто даже в C. Железяка-то наверняка шлёт данные подряд, без выравнивания, а у Вас структура не packed. Не говоря о том, что Вы не учитываете порядок байт в пакете, так что такой код не будет переносимым.
За выравнивание я просто не написал. Предполагая, что оно просто предполагается по умолчанию. Писал, чтобы не загромождать.
То же, по поводу переносимости - оно просто часто не предполагается. Если надо, то endian можно тоже менять глобально.
Меня больше интересовало, можно ли это сделать красивее, хотя бы так, как в тот же C. Чтобы при изменении порядка данных в структуре, я менял только структуру, а не 100500 классов, использующих эту структуру.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Эхо разума
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu
Контактная информация:

Re: JAVA

Сообщение serzh-z »

devilr писал(а):
26.06.2018 11:35
Чтобы при изменении порядка данных в структуре, я менял только структуру, а не 100500 классов, использующих эту структуру.
По-моему, это уже не проблема языка, а проблема дизайна приложения.
Спасибо сказали:
yoshakar
Сообщения: 259
ОС: Debian Stretch

Re: JAVA

Сообщение yoshakar »

devilr писал(а):
26.06.2018 11:35
Чтобы при изменении порядка данных в структуре, я менял только структуру, а не 100500 классов, использующих эту структуру.
Позвольте спросить, а как вы умудрились написать сериализацию/десериализацию простой структуры так, что при измерении порядка передаваемых данных надо менять 100500 классов? В конце-концов, Java поддерживает ООП, а в ООП есть такая штука как инкапсуляция..
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: JAVA

Сообщение NickLion »

Лично бы избегал таких задач в Java, не лучший язык для такого. Более того, даже сериализатор в POD-binary нормальный не написать, т.к.
https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getFields-- писал(а):The elements in the returned array are not sorted and are not in any particular order
, т.е. порядок никто не гарантирует.
ТруЪ Java путь, наверное, добавить аннотации для упорядочивания и другой информации.
devilr писал(а):
26.06.2018 01:21
uint16_t prefix
И тоже не получится, нет в Java unsigned типов. Придётся заводить int и в нём хранить значения от 0 до 65535. И контролировать по возможности.
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3667
ОС: Mandriva => Gentoo (~amd64)
Контактная информация:

Re: JAVA

Сообщение devilr »

NickLion писал:
26.06.2018 14:02
Лично бы избегал таких задач в Java, не лучший язык для такого.
Это да, но не всегда это возможно. Просто пример: андроид. И железяка, прикидывающаяся UARTом. И программист, знающий только JAVA.
По идее, если бы обработку потока данных от этой железки можно было бы просто написать на JAVA - было бы вообще прекрасно. Без всяких вставок, драйверов и прочих низкоуровневых штук.
Вообще, довольно странно, что в JAVA отказались от указателей и структур. Могли бы, хотя бы, объявить их "не безопасными" и оставить на откуп программисту.
Ну, на нет и суда нет.
Всем спасибо за участие!
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Эхо разума
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: JAVA

Сообщение NickLion »

Даже если бы они были, их полезность была бы близка к нулевой из-за отсутствия unsigned типов (которые в структурах используются довольно часто). Так что придётся использовать ByteBuffer, там и Big/Little Endian задать можно.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20790
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: JAVA

Сообщение Bizdelnick »

devilr писал(а):
26.06.2018 14:44
андроид. И железяка, прикидывающаяся UARTом. И программист, знающий только JAVA.
NDK же есть. Можно сделать сишную либу с джавовскими биндингами.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
devilr
Сообщения: 3667
ОС: Mandriva => Gentoo (~amd64)
Контактная информация:

Re: JAVA

Сообщение devilr »

Bizdelnick писал:
26.06.2018 19:51
devilr писал(а):
26.06.2018 14:44
андроид. И железяка, прикидывающаяся UARTом. И программист, знающий только JAVA.
NDK же есть. Можно сделать сишную либу с джавовскими биндингами.
А можете подсказать, как? Или пример какой может где есть...
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Эхо разума
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20790
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: JAVA

Сообщение Bizdelnick »

devilr писал(а):
26.06.2018 20:31
А можете подсказать, как? Или пример какой может где есть...
Ну как-то начиная отсюда и дальше.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Ответить