Int Literals

A direct (literal) expression of an integral, (non-decimal), value in source code.

Integer literals are used to directly write the value of an integral type in source code. They can be used to specify an exact value for chars, bytes, shorts, ints, and longs.

An integer literal is always a single token.

Syntax

Integer literals can be expressed through four forms:

1 decimal-literalinteger-type-suffix
2 hexadecimal-literalinteger-type-suffix
3 octal-literalinteger-type-suffix
4 binary-literalinteger-type-suffix

where...

decimal-literal is either:
  1. the digit 0, or
  2. a non-zero decimal digit (1, 2, 3, 4, 5, 6, 7, 8, 9)
followed by any number of decimal digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
hexadecimal-literal is the string prefix 0x or 0X, followed by at least one hexadecimal digit (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, A, B, C, D, E, F)
octal-literal is the digit 0 followed by at least one octal digit (0, 1, 2, 3, 4, 5, 6, 7)
binary-literal is the string prefix 0b or 0B, followed by at least one binary digit (0, 1)
integer-type-suffix is the letter L or l
The prefix itself is not composed of digits and therefore cannot have interleaved underscores; 0_x123 and 0x_123 are both invalid, for example.

such that...

Syntax Elements

1 A decimal integer literal (base 10), using digits 0 through 9.

2 A hexadecimal integer literal (base 16), using the same digits as base 10 as well as digits A through F with values 10 through 15. Capitalization is ignored, so A is equivalent to a, B to b, etc.

3 An octal integer literal (base 8), using digits 0 through 7. The 0 prefix is only used to signify that the literal is in octal notation and does not otherwise affect the literal's value.

4 A binary integer literal (base 2), using digits 0 and 1.

Interpretation

Decimal integer literals can represent:

Binary, octal, and hexadecimal integer literals can represent:

Decimal Interpretation

Decimal literals are interpreted as written. This means that one can expect the same text that makes up such a literal in source code to be printed if such literal is an argument of System.out.println():

System.out.println(1234567890);

Output:

1234567890

It is not possible for a decimal literal to represent a negative number; negative numbers derived from decimal literals can be obtained using the unary minus operator with the decimal literal as the operand. Special usage is granted to the literals 2147483648 and 9223372036854775808L, which can both be used only as the operand of the unary minus operator:

// int x = 2147483648;	// Syntax error: 2147483648 out of range for type int.
   int y = -2147483648;	// Valid

See the below example for more details.

Note that 2147483648L (and 2147483648l) can be used in contexts other than as the operand of the unary minus operator, since these are long literals and not int literals.

Decimal literals are required to have the long suffix (l or L) if they are out of range for the type int and can, thus, only be represented as a long literal. This occurs when a decimal literal is greater in value than 2147483647 and is not the literal 2147483648 as the operand of a unary minus:

long x = 2147483647; // In-range for type int
long y = 2147483648L; // Out of range for int, requires L (or l) suffix
long z = 10000000000L; // Out of range for int

long negative = -2147483648; // Suffix not required since literal is 2147483648 and is operand for unary minus (-)

Binary, Octal, and Hexadecimal Literals Interpretation

Binary, octal, and hexadecimal literals are interpreted as if used to specify the bits of a number, in two's complement.

Two's Complement

In two's complement format, the sign bit is used to denote the sign of the number and the remaining bits are used to determine the number's magnitude. The number is negative if the leftmost bit is 1, otherwise the number is positive. To determine the magnitude of the number, the remaining (value) bits are interpreted as a positive integer number and are added to,

The sign bit can be interpreted as adding the lowest (negative) value representable by the number, to the number when 1, and having no effect on the number when 0. See the examples below for more details.

Octal & Hexadecimal

Octal and hexadecimal literals' formats provide compact ways to specify the bits of a number in the same way that binary literals do. Each hexadecimal digit expresses 4 bits and each octal digit expresses 3.

int low = 0x8_0000000; // 8 hex digits is 32 bits of data
int lowInBinary = 0b1000_0000000000000000000000000000;
System.out.println(low);
System.out.println(lowInBinary);

Output:

-2147483648
-2147483648

Examples

Simple Usage

41 declared both as binary and decimal literals:

int x = 0b00101001; // 41
int y = 41;
System.out.println(x == y); // Prints true
Output:
true

A for loop that loops 16 times, starting at 0xF ( 15 ), down to 0 :

for (int i = 0xF; i >= 0x0; i--)
	System.out.println(i);	// println(...) prints integers in decimal (base 10)

Output:

15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0

Bitflags & Bitmasks

Demonstration of bitmasking using a bitflag named FLAG :

int x = 0b0110; // equal to 6
final int FLAG = 0b0001;

// Enable flag:
x |= FLAG;// x is now 0b0111 which is equal to 7

// Disable flag:
x ^= FLAG;// x is now 0b0110 which is 6

// Check for flag:
boolean flagOn = (x & FLAG) != 0;
if (flagOn)
   doSomething();

Octal Numbers

Example depicting equivalence between 3-bit parts of a number and single octal digits:

// Each octal digit is 3 bits
System.out.println(0b111 == 07); // true
System.out.println(0b111000 == 070); // true

// Octal 7 is binary 111
// Octal 0 is binary 000
System.out.pintln(0b111_000_111_000 == 07070); // true
Output:
true
true
true

Two's Complement & Negative Literals

A number has its lowest possible value when only its sign bit is 1 and all other bits are 0.

int x = 0b1_0000000000000000000000000000000;	// 32 bits. All bits but the sign bit are 0.
				// Notice the leftmost bit (before the underscore); it is the sign bit.
System.out.println(x);

That code outputs: -2147483648 which is the minimum value of an int.

Changing the rightmost value bit to a 1 will increment the number:

int x = 0b1_0000000000000000000000000000001; // Rightmost bit is 1
System.out.println(x);

This code outputs: -2147483647.

Changing the sign bit causes the number to be the numeric value of its value bits added with 0, rather than -2147483648:

int x = 0b0_0000000000000000000000000000001;
System.out.println(x);

Output:

1

The same can be applied to integer literals with the long suffix, although those comprise 64 bits rather than 32:

int x = 0b1_000000000000000000000000000000000000000000000000000000000000000L;
int y = 0b1_000000000000000000000000000000000000000000000000000000000000001L;
int z = 0b0_000000000000000000000000000000000000000000000000000000000000001L;
System.out.println(x);
System.out.println(y);
System.out.println(z);

Output:

-9223372036854775808
-9223372036854775807
1

Restrictions on Minimum Int/Long Literals

The literals 2147483648 and 9223372036854775808L cannot be written in a program unless they are the immediate operand of a unary minus operator:

   int a = 50;
   int b = 2147483647;	// Largest possible int value
// int c = 2147483648;	// Invalid: Literal is larger than largest possible int
   int d = -50;
   int e = -2147483647;
   int f = -2147483648;	// Smallest possible int value
// int g = -2147483649;	// Invalid: Literal is smaller than smallest possible int

This restriction is in place because the int type can represent numbers from 2147483647 to -2147483648, and positive 2147483648 is outside of that range. (Similarly, the long type ranges from 9223372036854775807L to -9223372036854775808L.)

Notes

  1. 0 is the only integer literal whose leftmost digit is 0 that is not an octal literal.
  2. The restriction that the literals 2147483648 and 9223372036854775808L may only be operands of the unary minus operator is at the syntactic level, and so, while the following is allowed:
       int small1 = -2147483648;	// Valid: 2147483648 is immediate operand of -
       int small2 = - 2147483648;	// Valid: 2147483648 is immediate operand of -
       int small3 = --2147483648;	// Valid: 2147483648 is immediate operand of -, (but this constant expression will exhibit overflow)
       int small4 = (-2147483648);	// Valid: 2147483648 is immediate operand of -

    this is not:

    // int small5 = -(2147483648);	// Invalid: 2147483648 is not the immediate operand of -
    								// (2147483648) is the immediate operand of -