404

Is there a way to declare an unsigned int in Java?

Or the question may be framed as this as well: What is the Java equivalent of unsigned?

Just to tell you the context I was looking at Java's implementation of String.hashcode(). I wanted to test the possibility of collision if the integer were 32 unsigned int.

Lii
  • 11,553
  • 8
  • 64
  • 88
Harshdeep
  • 5,614
  • 10
  • 37
  • 45
  • 10
    There are no unsigned types in Java. – Andrew Logvinov Mar 24 '12 at 18:11
  • 1
    This post might help you http://stackoverflow.com/a/4449161/778687 – tusar Mar 24 '12 at 18:11
  • See here: http://stackoverflow.com/questions/1841461/unsigned-short-in-java – j13r Mar 24 '12 at 18:12
  • 2
    Doesn't seem to be a way AFAICT. Related: http://stackoverflow.com/questions/430346/why-doesnt-java-support-unsigned-ints – James Manning Mar 24 '12 at 18:13
  • 15
    It depends on the purpose you're trying to achieve. For most purposes, all integers in Java are signed. However, you can *treat* a signed integer as unsigned in one specific case: you can shift right without sign extending by using `>>>` operator instead of `>>`. – Sergey Kalinichenko Mar 24 '12 at 18:19
  • Java is coming to allown `unsigned` in Java SE 8 – chinglun Nov 25 '13 at 00:16
  • Good to know that there are options to do logical shifts and such, instead of only arithmetic ones. Still, Java makes it hard to handle specialized file formats or just those from decades ago. – Florian R. Klein Jan 21 '14 at 16:02
  • Don't forget about 'char'. It's a 16bit unsigned integer. Can even be used as an array index. Just need to typecast to (int) to print it as number instead of character. – Peter Quiring Jun 24 '14 at 16:00
  • http://stackoverflow.com/a/397997/49246 – starblue Sep 01 '14 at 07:32
  • 2
    See also [How to use the unsigned Integer in Java 8 and Java 9?](https://stackoverflow.com/questions/25556017/how-to-use-the-unsigned-integer-in-java-8-and-java-9) – Vadzim Mar 03 '18 at 19:00

10 Answers10

392

Java does not have a datatype for unsigned integers.

You can define a long instead of an int if you need to store large values.

You can also use a signed integer as if it were unsigned. The benefit of two's complement representation is that most operations (such as addition, subtraction, multiplication, and left shift) are identical on a binary level for signed and unsigned integers. A few operations (division, right shift, comparison, and casting), however, are different. As of Java SE 8, new methods in the Integer class allow you to fully use the int data type to perform unsigned arithmetic:

In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 2^32-1. Use the Integer class to use int data type as an unsigned integer. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.

Note that int variables are still signed when declared but unsigned arithmetic is now possible by using those methods in the Integer class.

Aleksandr Dubinsky
  • 22,436
  • 15
  • 82
  • 99
Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
  • 11
    To be fair, for many projects the technical requirements aren't that strict and you can indeed afford to "waste" memory like that. – Simeon Visser Jun 18 '13 at 07:37
  • 6
    I know, I also understand the original purpose of Java. But for example Smartphones do not dispose with extra memory. And they usually use Java, as far as I know. But well, I don't want to start a war between Java programers and the others. – Tomáš Zato Jun 18 '13 at 08:24
  • 151
    To me this isn't just a case of wasting money. When you work on a bit level, unsigned is simply easier to work with – Cruncher Sep 19 '13 at 14:30
  • 38
    **As of Java 8, this is no longer true**. In Java SE 8 and later, you can use the `int` data type to represent an unsigned 32-bit integer, which has a minimum value of `0` and a maximum value of `2^32-1`. - see http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html and http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html – 8bitjunkie Jan 05 '15 at 11:26
  • 7
    @7SpecialGems: I have updated the answer to include that information. That being said, it's not possible to declare unsigned integers or exclude negative values, it's only possible to use an `int` as if it were unsigned by using various methods. – Simeon Visser Jan 12 '15 at 22:59
  • 1
    I nowadays use Java when its convenient, I know better the differences between languages and platforms, pros and cons. Java still bothers me with "You can't use local variables in Lambdas like you do with C#, bud", but I've been dealing with it. :v – Felype Feb 15 '16 at 11:23
  • @SimeonVisser I'm having difficulty in understanding the use and big deal over having the ability to use unsigned datatypes. From the various sources online I read from, it seems like it revolves around just widening the maximum value, and the implicit by nature guarantee that it's a positive number. Is my understanding correct, or are there other major reasons? Also, now that the `Integer` class in Java 8 allows one to use unsigned int, is the difference between just in space and speed (since in C/C++ they're primitive, while in Java, it's a whole object wrapper) – Honinbo Shusaku Aug 17 '16 at 17:48
  • @Cruncher forgive my ignorance on low level development, but why is it much easier to work with unsigned ints at the bit level? – Honinbo Shusaku Aug 17 '16 at 17:49
  • 1
    @Abdul: there is no “difference between just in space and speed”, as `int` in Java is a primitive type. The methods for using these primitive values as unsigned are located in the class `Integer`, but this doesn’t imply that you need `Integer` objects (these methods are `static`). – Holger Mar 20 '17 at 10:27
  • 2
    @SimeonVisser there is no waste of memory, but a different interpretation of the MSB, also it useful to have a better representation of your data structure/variables. eg: if you are doing something with N number it would be silly to use a signed integer the right type is unsigned int/long/blablbabla. The JVM should be evolved with unsigned type. C# .NET has those ones for eg. it would help – Raffaello Oct 06 '17 at 08:45
  • 1
    @8bitjunkie if max value is 2^32 - 1 it kind of sounds like Java is just willing to lie to you and tell you a signed int in a wrapper is a true unsigned int. – Max von Hippel Dec 06 '17 at 06:26
  • Does declaring int work in Android as a unsigned int? Google tells that its supports some features of Android 8 but there is not much information in this link - https://developer.android.com/studio/write/java8-support – Mahadevan Sreenivasan May 25 '18 at 07:36
85

Whether a value in an int is signed or unsigned depends on how the bits are interpreted - Java interprets bits as a signed value (it doesn't have unsigned primitives).

If you have an int that you want to interpret as an unsigned value (e.g. you read an int from a DataInputStream that you know should be interpreted as an unsigned value) then you can do the following trick.

int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffL;

Note: it is important that the hex literal is a long literal, not an int literal - hence the 'L' at the end.

Zsolt Safrany
  • 13,290
  • 6
  • 50
  • 62
  • 3
    For me this is the best answer... My data comes from an NFC card UID, which can have 4 or 8 bytes... In the case of 4 bytes I needed to cast it to an unsigned int, and I couldn't use ByteBuffer.getLong because it was not 64-bit data. Thanks. – Loudenvier May 08 '14 at 01:40
  • 1
    Why does it need to be a long. Can't you just do `0xFFFFFF` and keep the int? – Displee Feb 10 '20 at 14:09
  • 1
    @Displee Just think that through. If you AND an int with 32 bits of 1s, why would Java interpret your new variable any differently than the original value? That‘s 8 F‘s, not 6, btw, because 0xF=1111 and you need 32 of those 1s) – Jonathan Komar Mar 06 '22 at 21:39
  • Why don't you directly do `long unsignedValue = someObject.getInt();`? What is the benefits of "ANDing" that `int` value with 0xFFFFFFFFL? – Mohammad Kholghi Oct 04 '22 at 04:57
  • And another question: Why do you put an "L" at the end of `0xFFFFFFFFL`? Isn't `0xFFFFFFFF` enough? – Mohammad Kholghi Oct 04 '22 at 04:58
  • 2
    @MohammadKholghi casting an int to long will sign-extend (i.e., if the int would be negative, the long will be negative). in effect this means all upper bits of the long get set to 1. if you mask against 32 bits, you will get only those 32 bits, so it will always be positive. the "L" at the end makes it a long literal rather than an int – devyn Nov 29 '22 at 10:44
28

We needed unsigned numbers to model MySQL's unsigned TINYINT, SMALLINT, INT, BIGINT in jOOQ, which is why we have created jOOU, a minimalistic library offering wrapper types for unsigned integer numbers in Java. Example:

import static org.joou.Unsigned.*;

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

All of these types extend java.lang.Number and can be converted into higher-order primitive types and BigInteger. Hope this helps.

(Disclaimer: I work for the company behind these libraries)

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
9

For unsigned numbers you can use these classes from Guava library:

They support various operations:

  • plus
  • minus
  • times
  • mod
  • dividedBy

The thing that seems missing at the moment are byte shift operators. If you need those you can use BigInteger from Java.

randers
  • 5,031
  • 5
  • 37
  • 64
Andrejs
  • 26,885
  • 12
  • 107
  • 96
5

Perhaps this is what you meant?

long getUnsigned(int signed) {
    return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
  • getUnsigned(0) → 0
  • getUnsigned(1) → 1
  • getUnsigned(Integer.MAX_VALUE) → 2147483647
  • getUnsigned(Integer.MIN_VALUE) → 2147483648
  • getUnsigned(Integer.MIN_VALUE + 1) → 2147483649
Matthias Ronge
  • 9,403
  • 7
  • 47
  • 63
  • You're sacrificing a zillionth of a second of performance time for lazy typing with ternary operators instead of if statements. Not good. (kidding) – rassa45 Apr 05 '16 at 02:37
  • 7
    Do you really think, `2 * (long) Integer.MAX_VALUE + 2` is easier to understand than `0x1_0000_0000L`? In that regard, why not simply `return signed & 0xFFFF_FFFFL;`? – Holger Jan 09 '17 at 18:58
5

Use char for 16 bit unsigned integers.

  • Char are not 32bit unsigned int but char is a good answer for memory gain. this link : https://stackoverflow.com/questions/1841461/unsigned-short-in-java (from jqr above) – blobmaster Jan 10 '19 at 08:04
5

There are good answers here, but I don’t see any demonstrations of bitwise operations. Like Visser (the currently accepted answer) says, Java signs integers by default (Java 8 has unsigned integers, but I have never used them). Without further ado, let‘s do it...

RFC 868 Example

What happens if you need to write an unsigned integer to IO? Practical example is when you want to output the time according to RFC 868. This requires a 32-bit, big-endian, unsigned integer that encodes the number of seconds since 12:00 A.M. January 1, 1900. How would you encode this?

Make your own unsigned 32-bit integer like this:

Declare a byte array of 4 bytes (32 bits)

Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)

This initializes the array, see Are byte arrays initialised to zero in Java?. Now you have to fill each byte in the array with information in the big-endian order (or little-endian if you want to wreck havoc). Assuming you have a long containing the time (long integers are 64 bits long in Java) called secondsSince1900 (Which only utilizes the first 32 bits worth, and you‘ve handled the fact that Date references 12:00 A.M. January 1, 1970), then you can use the logical AND to extract bits from it and shift those bits into positions (digits) that will not be ignored when coersed into a Byte, and in big-endian order.

my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed

Our my32BitUnsignedInteger is now equivalent to an unsigned 32-bit, big-endian integer that adheres to the RCF 868 standard. Yes, the long datatype is signed, but we ignored that fact, because we assumed that the secondsSince1900 only used the lower 32 bits). Because of coersing the long into a byte, all bits higher than 2^7 (first two digits in hex) will be ignored.

Source referenced: Java Network Programming, 4th Edition.

Community
  • 1
  • 1
Jonathan Komar
  • 2,678
  • 4
  • 32
  • 43
2

It seems that you can handle the signing problem by doing a "logical AND" on the values before you use them:

Example (Value of byte[] header[0] is 0x86 ):

System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));

Result:

Integer -122 = 134
Artem
  • 3,304
  • 3
  • 18
  • 41
1

Just made this piece of code, wich converts "this.altura" from negative to positive number. Hope this helps someone in need

       if(this.altura < 0){    

                        String aux = Integer.toString(this.altura);
                        char aux2[] = aux.toCharArray();
                        aux = "";
                        for(int con = 1; con < aux2.length; con++){
                            aux += aux2[con];
                        }
                        this.altura = Integer.parseInt(aux);
                        System.out.println("New Value: " + this.altura);
                    }
Romulo
  • 21
  • 3
-28

You can use the Math.abs(number) function. It returns a positive number.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kyo722
  • 1
  • 1