如何在Java 8和Java 9中使用无符号整数?


81

在Oracle“原始数据类型”页面中,它提到Java 8添加了对无符号int和long的支持:

int:默认情况下,int数据类型是32位带符号的二进制补码整数,其最小值为-2 31,最大值为2 31 -1。在Java SE 8和更高版本中,可以使用int数据类型表示无符号的32位整数,其最小值为0,最大值为2 32 -1。使用Integer该类可将int数据类型用作无符号整数。有关更多信息,请参见“数字类”部分。像静态方法compareUnsigneddivideUnsigned等已被添加到Integer类,以支持算术运算的无符号整数。

longlong数据类型是64位二进制补码整数。带符号long的最小值为-2 63,最大值为2 63 -1。在Java SE 8和更高版本中,可以使用long数据类型表示无符号的64位long,其最小值为0,最大值为2 64 -1。当您需要一个比int提供的值宽的值范围时,请使用此数据类型。该Long班还包含方法,如compareUnsigneddivideUnsigned等支持算术运算的无符号long

但是,我发现没有办法声明无符号的long或integer。例如,以下代码在应该在范围内时(给出的值恰好是2 64 -1)给出了“文字超出范围”的编译器错误消息(我使用的是Java 8 )。 :

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

那么,有什么方法可以声明一个无符号的int或long?


2
在Java 8中,您的Long.MAX_VALUE常量返回什么?
布鲁诺·佛朗哥

21
没有无符号整数或无符号长类型。如果您使用新方法之一,则该方法将32位或64位整数视为未签名。但是,仅此而已。变量的类型仍将是带符号的,并且要记住要使用它作为无符号数字。他们没有添加未签名的文字,但是如果有足够多的人对它们进行调试,也许他们会将它们添加到Java 9中。:)
2014年

5
除了添加新方法外,他们并没有真正更改任何内容。
Hot Licks

4
据我所知,它们所做的只是添加方法,这些方法可以返回无符号值,但不允许您声明无符号值。如果您问我,那是一种愚蠢,是一种真正的痛苦。我想知道是否有一种方法是使用Integer.divideUnsigned,其中一个参数为1,另一种是您希望视为无符号的任何数字。据我所知,它可以工作,但似乎是一种愚蠢的做事方式。
cluemein

@ajb在“调试”过程中如何获得帮助,以最终在Java中看到正确的未签名?:)
Matthieu

Answers:


51

根据您发布的文档以及此博客文章-声明未签名的int / long和已签名的int / long之间的原语没有什么区别。“新支持”是在Integer和Long类中添加了静态方法,例如Integer.divideUnsigned。如果不使用这些方法,则2 ^ 63-1以上的“无符号”长整型是带有负值的普通旧长整型。

快速浏览一下,似乎没有一种方法可以在+/- 2 ^ 31-1或超出+/- 2 ^ 63-1的范围内声明整数常量。您将必须手动计算与超出范围的正值相对应的负值。


85

好吧,即使在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提供了这样的ID)并想对其进行排序,也许是因为我知道它们是按时间顺序排列的,那么Long.MAX_VALUE以外的所有内容实际上都会在0之前显示为负数。随着Java的实现:-(相反,它似乎还必须转移下来,从而无符号0映射到签署Long.MIN_VALUE。
大卫·斯迈利

10
@DavidSmiley好点。要对无符号的long进行排序,请使用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
     */

9
应该添加一些解释,而不仅仅是在此处添加代码。
cluemein

20

有没有办法如何来声明一个无符号长或者int在Java中8或Java 9.但有些方法对待他们,好像他们是无符号,例如:

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

但这不是变量的声明


3
我受伤了,为什么不呢。他们可以轻松添加uint和ulong类型
-EKanadily

@docesam在这个这个实况是详细的解释。简而言之,仅添加了对Integer类进行无符号操作的方法。如果他们可以轻松添加,我不知道为什么他们不这样做;-)
1ac0 2016年

@ Ladislav DANKO有审慎的人,还有其他人。我不确定(在这种情况下)是否审慎,但我的印象是oracle不太审慎。
EKanadily

1
@docesam不,他们不能“轻松添加uint和ulong类型”。这将需要彻底检查JLS,JVM规范,JNI,许多库(例如java.util.Arrays),反射等。
Nayuki

1
@ Michaelangel007嘿,我认为我们正在以不同的背景假设来探讨这个话题。希望向我发送电子邮件,我们会谈谈细节吗?
Nayuki's

4

如果使用第三方库是一种选择,有女王(一个分拆库从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

(免责声明:我为这些库背后的公司工作)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.