web-dev-qa-db-fra.com

Comment utiliser l'entier non signé dans Java 8 et Java 9?

Dans les "Types de données primitifs" Oracle page , il est mentionné que Java 8 ajoute la prise en charge des ints et des unsigned longs:

int: Par défaut, le type de données int est un entier du complément à deux signé 32 bits, dont la valeur minimale est de −2.31 et une valeur maximale de 231−1. Dans Java SE 8 et versions ultérieures, vous pouvez utiliser le type de données int pour représenter un entier non signé de 32 bits, dont la valeur minimale est 0 et une valeur maximale de 232−1. Utilisez la classe Integer pour utiliser le type de données int en tant qu'entier non signé. Voir la section Les classes de nombres pour plus d'informations. Des méthodes statiques telles que compareUnsigned, divideUnsigned etc ont été ajoutées à la classe Integer pour prendre en charge les opérations arithmétiques des entiers non signés.

long: Le type de données long est un entier complémentaire de 64 bits. Le signe long a une valeur minimale de −263 et une valeur maximale de 263−1. Dans Java SE 8 et versions ultérieures, vous pouvez utiliser le type de données long pour représenter un long 64 bits non signé, qui a un minimum valeur de 0 et une valeur maximale de 264−1. Utilisez ce type de données lorsque vous avez besoin d'une plage de valeurs plus large que celles fournies par int. La classe Long contient également des méthodes telles que compareUnsigned, divideUnsigned etc pour prendre en charge les opérations arithmétiques de unsigned long.

Cependant, je ne trouve aucun moyen de déclarer un entier ou un entier non signé. Le code suivant, par exemple, donne un message d'erreur du compilateur du type "le littéral est en dehors de la plage" (j'utilise Java 8, bien sûr), alors qu'il devrait être dans la plage (la valeur affectée est précisément 264−1):

public class Foo {
    static long values = 18446744073709551615L;

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

Alors, y at-il un moyen de déclarer un unsigned int ou long?

77
Pabce

Selon la documentation que vous avez postée, et cet article de blog - il n'y a pas de différence lorsque vous déclarez la primitive entre un unsigned int/long et un autre signé. Le "nouveau support" est l’ajout des méthodes statiques dans les classes Integer et Long, par exemple. Integer.divideUnsigned . Si vous n'utilisez pas ces méthodes, votre "unsigned" long au-dessus de 2 ^ 63-1 est tout simplement un vieil homme long avec une valeur négative.

D'un coup d'œil rapide, il ne semble pas qu'il soit possible de déclarer des constantes entières comprises entre +/- 2 ^ 31-1 ou +/- 2 ^ 63-1 pour les longs. Vous devez calculer manuellement la valeur négative correspondant à votre valeur positive hors limites.

46
Sbodd

Eh bien, même dans Java 8, long et int sont toujours signés, seules certaines méthodes les traitent comme si elles n'étaient pas signées. Si vous voulez écrire unsigned long littéral comme ça, vous pouvez le faire

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

public static void main(String[] args) {
    System.out.println(values); // -1
    System.out.println(Long.toUnsignedString(values)); // 18446744073709551615
}
81
kajacx
    // 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
     */
23
blueberry0xff

Il n'y a aucun moyen de savoir comment déclarer un nsigned long or int dans Java 8 ou Java 9. Cependant, certaines méthodes les traitent comme si elles n'étaient pas signées, par exemple:

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

mais ce n'est pas déclaration de la variable.

17
1ac0

Si l'utilisation d'une bibliothèque tierce est une option, il existe jOO (une bibliothèque dérivée de jOOQ ), qui propose des types d'encapsuleur pour les nombres entiers non signés en Java. Ce n'est pas exactement la même chose que d'avoir un support de type primitif (et donc de code d'octet) pour les types non signés, mais c'est peut-être encore suffisant pour votre cas d'utilisation.

import static org.joou.Unsigned.*;

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

Tous ces types étendent Java.lang.Number et peuvent être convertis en types primitifs d'ordre supérieur et BigInteger.

(Avertissement: je travaille pour l'entreprise derrière ces bibliothèques)

3
Lukas Eder