Як використовувати ціле число без підпису в Java 8 та Java 9?


82

У Oracle «Примітивні типи даних» сторінки , він згадує , що Java 8 додана підтримка для беззнакових цілих чисел і довгих позицій:

int: За замовчуванням intтип даних - це 32-розрядне ціле доповнення, підписане двома, яке має мінімальне значення −2 31 та максимальне значення 2 31 −1. У Java SE 8 та пізніших версіях ви можете використовувати intтип даних для представлення 32-бітового цілого числа без підпису, яке має мінімальне значення 0 та максимальне значення 2 32 -1. Використовуйте Integerклас, щоб використовувати intтип даних як ціле без знака. Для отримання додаткової інформації дивіться розділ Класи чисел. Статичні методи , такі як compareUnsigned, і divideUnsignedт.д. , які були додані до Integerкласу для підтримки арифметичних операцій для цілих чисел без знака.

long: Тип longданих - це 64-розрядне ціле доповнення. longМінімальне значення підписаного - -2 63 та максимальне значення 2 63 -1. У Java SE 8 та пізніших версіях ви можете використовувати longтип даних для представлення 64-розрядного без підпису long, що має мінімальне значення 0 та максимальне значення 2 64 −1. Використовуйте цей тип даних, коли вам потрібен діапазон значень, ширший за ті, що надаються int. LongКлас також містить методи , такі як compareUnsigned, і divideUnsignedт.д. , щоб підтримувати арифметичні операції для беззнакового long.

Однак я не знаходжу способу оголосити непідписане довге або ціле число. Наступний код, наприклад, дає повідомлення про помилку компілятора "літерал поза діапазоном" (я, звичайно, використовую Java 8), коли він повинен бути в діапазоні (присвоєне значення - саме 2 64 -1) :

public class Foo {
    static long values = 18446744073709551615L;
    
    public static void main(String[] args){
        System.out.println(values);
    }  
}

Отже, чи є спосіб заявити непідписаний int або long?


2
Що повертається у вашій константі Long.MAX_VALUE у Java 8?
Бруно Франко

21
Немає беззнакового цілого чи непідписаного довгого типу. Якщо ви використовуєте один із нових методів, цей метод буде обробляти 32-розрядне або 64-розрядне ціле число, ніби воно було без підпису. Але це все. Тип змінної все одно буде підписаний, і вам залишається пам’ятати, що ви використовуєте її як номер без підпису. Вони не додавали непідписані літерали, але, можливо, вони додадуть їх до Java 9, якщо достатня кількість людей буде їх помиляти. :)
ajb

5
Вони насправді нічого не змінили, крім додавання нових методів.
Hot Licks

4
Наскільки я можу зрозуміти, все, що вони зробили, - це додавання методів, які можуть повертати непідписані значення, але не дозволяють оголошувати безпідписані значення. Якийсь дурний, якщо ви питаєте мене, і справжній біль. Цікаво, чи одним із способів буде використання Integer.divideUnsigned, причому один параметр дорівнює 1, а інший - будь-яке число, яке ви хочете обробляти як без підпису. Працював би, наскільки я можу зрозуміти, але, здається, це справді безглуздий спосіб робити щось.
cluemein

@ajb, як я можу допомогти в процесі "виправлення помилок", щоб нарешті побачити належне непідписане в Java? :)
Matthieu

Відповіді:


52

За документацією, яку ви опублікували, і за цим дописом у блозі - немає жодної різниці при оголошенні примітиву між непідписаним int / long та підписаним. "Нова підтримка" - це додавання статичних методів у класи Integer та Long, наприклад Integer.divideUnsigned . Якщо ви не використовуєте ці методи, ваш "без підпису" довжиною вище 2 ^ 63-1 - це звичайний старий лонг з від'ємним значенням.

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


88

Ну, навіть у Java 8, longі intвони все ще підписані, лише деякі методи обробляють їх так, ніби вони були без підпису . Якщо ви хочете написати 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
}

5
Спостереження, яке я бачу з цього приводу, полягає в тому, що впорядкування пошкоджене. Якби я хотів отримати непідписаний long з якоїсь системи (Twitter, до речі, надає такі ідентифікатори) і хотів би їх сортувати, можливо, тому, що я знав, що вони хронологічні, то все, що перебуває за межами Long.MAX_VALUE, фактично відображатиметься до 0 як негатив з реалізацією Java :-(. Натомість, схоже, потрібно також зрушити його вниз так, щоб непідписані 0 карти підписали Long.MIN_VALUE.
Девід Смайлі

10
@DavidSmiley Хороший момент. Для сортування непідписаних довжин використовуйте Long.compareUnsigned або передайте цей метод як порівняльник для сортування функцій,
kajacx

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

10
Потрібно додати якесь пояснення, а не просто викинути там код.
cluemein

22

Там немає ніякого способу , як оголосити беззнаковое довге або Int в Java 8 або Java 9. Але деякі методи лікування їх , як якщо б вони були без знака, наприклад:

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

але це не оголошення змінної.


3
я гадаю, чому ні. вони могли легко додати типи uint і ulong
EKanadily

@docesam у цьому та цьому документі є докладним поясненням. коротше, додано лише методи для маніпуляцій без підпису до класу Integer. і якщо вони могли легко додати, я не знаю, чому вони цього не будуть робити ;-)
1ac0

@ Ладислав ДАНКО є розсудливі люди, а є й інші хлопці. я не впевнений, чи в цьому випадку він був розсудливим чи ні, але, на моє враження, оракул не такий розсудливий.
EKanadily

1
@docesam Ні, вони не могли мати "легко додані типи uint і ulong". Для цього знадобиться капітальний ремонт JLS, специфікація JVM, JNI, багато бібліотек (наприклад, java.util.Arrays), роздуми та багато іншого.
Наюкі

1
@ Michaelangel007 Привіт, я думаю, ми підходимо до цієї теми з різними припущеннями. Хочете передати мені електронний лист, і ми поговоримо про деталі?
Наюкі

4

Якщо використання сторонньої бібліотеки є варіантом, існує 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.

(Застереження: я працюю в компанії, яка стоїть за цими бібліотеками)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.