Есть ли библиотека Java для обложек типов без знака?
Очевидно, что Java не поддерживает типы беззнаковых чисел изначально, и это скоро не изменится (комментарии, начиная с 2002 года). Однако при работе с базами данных, такими как MySQL, они могут время от времени пригодиться. Существует много вопросов, касающихся моделирования неподписанных чисел. Например:
Все они поверхностно описывают, как это можно сделать. Но есть ли какая-нибудь библиотека, которая действительно идет полным ходом и реализует подходящие обертки для UByte
, UShort
, UInteger
, ULong
? Предпочтительно, чтобы эти обертки расширяли java.lang.Number
и предоставляли арифметический API, аналогичный API java.math.BigInteger
.
Как можно видеть в этом документе, есть много, о чем можно подумать, и многое, что может пойти не так (например, как побитовое сдвиг, как размножаться и т.д.), поэтому я не хочу делать это сам. Кроме того, я не хочу просто использовать следующий более высокий тип (например, Short
вместо Byte
и т.д.). Я хочу, чтобы, например, было указано число 8-bit
, 16-bit
, 32-bit
, 64-bit
, для лучшего взаимодействия с базами данных.
UPDATE
Прежде чем ответить! Учтите, что я знаю все обходные пути, но мне действительно очень хотелось иметь именно эти 4 типа с точно указанными выше свойствами. И, возможно, кто-то уже это сделал, поэтому я спрашиваю. Не нужно напоминать мне об обходных решениях.
Ответы
Ответ 1
Когда мне нужна эта функциональность внутри jOOQ, я не нашел ничего подобного, поэтому я перевернул собственный Open Source библиотеку, которую я называю jOOU (U для Unsigned):
http://github.com/jOOQ/jOOU
Я понимаю, что некоторые могут подумать, что это слишком много, но я бы очень хотел, чтобы именно эти обертки обменивали то, что называет другие языки ubyte
, ushort
, uint
, ulong
. Надеемся, что с Valhalla эти обертки можно превратить в типы значений.
Конечно, вклад в реализацию арифметики/побитовой операции очень приветствуется!
Ответ 2
Есть несколько причин, по которым никто не создал эти обертки так, как вы хотите.
- Производительность
- Накладные расходы сборщика мусора
- no autoboxing/unboxing
- плохой/бесполезный интерфейс.
- более простые способы борьбы с ним существуют
Первые четыре точки демонстрируются небольшим примером C:
unsigned int x=42, y, m=5, t=18;
y = x * m + t;
Это будет переведено на:
UInteger m = new UInteger(5);
UInteger t = new UInteger(18);
UInteger x = new UInteger(42);
UInteger y = x.multiplyBy(m);
y = y.add(t);
Необходимо создать несколько объектов-оболочек, multiplyBy
и add
будет генерировать еще несколько. Это приведет к некоторой нагрузке на сборщик мусора, если многие вычисления будут выполнены таким образом. Обертывание и разворачивание также не будут потреблять ваши процессоры.
То, что даже простая арифметика - это PITA для записи или чтения, также очевидна.
По тем же причинам NOBODY делает арифметику с использованием подписанных типов обертки.
Все это не нужно, если вы выполняете вычисления с использованием следующего более крупного типа и обрезаете верхнюю часть следующим образом:
long x=42, y, m=5, t=18
y = (x*m + t) & 0xFFFFFFFF;
Передача между Java и базой данных также может быть выполнена с использованием следующего большого подписанного типа. И поскольку JDBC не будет создавать эти неподписанные типы обертки, вам придется сделать именно это самостоятельно, чтобы преобразовать данные в беззнаковые обертки после этого.
Я сделал некоторую обработку данных с интенсивным процессором для себя и обработал двоичные протоколы. В этих случаях я хотел, чтобы у меня были и неподписанные типы данных. Но эмуляция их на Java с типами обертки была бы более проблематичной, чем решение проблемы непосредственно в каждом отдельном случае.
Ответ 3
Решение, которое используется в примитивах-примитивах для массива unsignedInt, чтобы пройти вокруг long, считает это как unsigned int. Вы можете прочитать здесь:
http://commons.apache.org/primitives/apidocs/org/apache/commons/collections/primitives/ArrayUnsignedIntList.html
Ответ 4
Другая библиотека для рассмотрения - Google Guava. Поддерживаются следующие неподписанные типы:
они расширяют число и осуществляют арифметические операции.
Ответ 5
// Java 8
int vInt = Integer.parseUnsignedInt("4294967295");
System.out.println(vInt); // -1
String sInt = Integer.toUnsignedString(vInt);
System.out.println(sInt); // 4294967295
long vLong = Long.parseUnsignedLong("18446744073709551615");
System.out.println(vLong); // -1
String sLong = Long.toUnsignedString(vLong);
System.out.println(sLong); // 18446744073709551615
// Guava 18.0
int vIntGu = UnsignedInts.parseUnsignedInt(UnsignedInteger.MAX_VALUE.toString());
System.out.println(vIntGu); // -1
String sIntGu = UnsignedInts.toString(vIntGu);
System.out.println(sIntGu); // 4294967295
long vLongGu = UnsignedLongs.parseUnsignedLong("18446744073709551615");
System.out.println(vLongGu); // -1
String sLongGu = UnsignedLongs.toString(vLongGu);
System.out.println(sLongGu); // 18446744073709551615