Как использовать целое число без знака в Java 8 и Java 9?

в Oracle "примитивные типы данных" страница, в нем упоминается, что Java 8 добавляет поддержку неподписанных ints и longs:

int по умолчанию int тип данных представляет собой 32-битное целое число, имеющее минимальное значение -231 и максимальное значение 231-1. в Java SE 8 и более поздних, вы можете использовать int тип данных для представления 32-разрядного целого числа без знака с минимальным значением 0 и максимальное значение 232-1. использовать Integer класс int тип данных как целое число без знака. Дополнительные сведения см. В разделе классы чисел. Статические методы, такие как compareUnsigned, divideUnsigned etc были добавлены в Integer класс для поддержки арифметических операций для целых чисел без знака.

long: элемент long тип данных-64-разрядное целое число дополнения two. Подписанный long минимальное значение -263 и a максимальное значение 263-1. в Java SE 8 и более поздних, вы можете использовать long тип данных для представления беззнаковое 64-битное long, который имеет минимальное значение 0 и максимальное значение 264-1. используйте этот тип данных, когда вам нужен диапазон значений шире, чем те, которые предоставлены int. The Long класс также содержит методы, такие как compareUnsigned, divideUnsigned etc для поддержки арифметических операций для unsigned long.

однако, я не нахожу способ объявления unsigned long или integer. Следующий код, например, дает сообщение об ошибке компилятора "литерал вне диапазона" (я использую Java 8, Конечно), когда он должен быть в диапазоне (назначенное значение точно 264-1):

public class Foo {
    static long values = 18446744073709551615L;

    public static void main(String[] args){
        System.out.println(values);
    }  
}

Итак, есть ли способ объявить unsigned int или long?

5 ответов


в документации вы выложили, и этот блог - нет никакой разницы при объявлении примитива между unsigned int / long и подписанным. "Новая поддержка" - это добавление статических методов в целочисленные и длинные классы, например целое число.divideUnsigned. Если вы не используете эти методы, ваш "неподписанный" длинный выше 2^63-1-это просто старый длинный с отрицательным значением.

от быстрого обезжиренного, не похоже, что есть способ объявления целочисленных констант в диапазоне вне + / - 2^31-1 или + / - 2^63-1 для лонгов. Вам придется вручную вычислить отрицательное значение, соответствующее положительному значению вне диапазона.


Ну, даже в Java 8, long и int все еще подписаны, только некоторые методы относитесь к ним как к неподписанным. Если вы хотите написать unsigned long литерал, как это, вы можете сделать

static long values = Long.parseUnsignedLong("18446744073709551615");

public static void main(String[] args) {
    System.out.println(values); // -1
    System.out.println(Long.toUnsignedString(values)); // 18446744073709551615
}

    // 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

    /**
     Integer - Max range
     Signed: From −2,147,483,648 to 2,147,483,647, from −(2^31) to 2^31 – 1
     Unsigned: From 0 to 4,294,967,295 which equals 2^32 − 1

     Long - Max range
     Signed: From −9,223,372,036,854,775,808 to 9,223,372,036,854,775,807, from −(2^63) to 2^63 − 1
     Unsigned: From 0 to 18,446,744,073,709,551,615 which equals 2^64 – 1
     */

нет никакого способа, как объявить an без знака long или int в Java 8 и Java 9. Но некоторые методы рассматривают их как неподписанные, например:

static long values = Long.parseUnsignedLong("123456789012345678");

но это не декларация переменной.


Если использование сторонней библиотеки является опцией, есть jOOU (библиотека спина от jOOQ), который предлагает типы оболочки для целых чисел без знака в Java. Это не совсем то же самое, что поддержка примитивного типа (и, следовательно, байтового кода) для неподписанных типов, но, возможно, это все еще достаточно хорошо для вашего варианта использования.

import static org.joou.Unsigned.*;

// and then...
UByte    b = ubyte(1);
UShort   s = ushort(1);
UInteger i = uint(1);
ULong    l = ulong(1);

все эти типы расширения java.lang.Number и могут быть преобразованы в более простые типы BigInteger.

(отказ от ответственности: я работаю в компании за этими библиотеками)