Java Number System
A complete guide to the Java Number System โ binary, octal, decimal, hexadecimal representations, base conversion methods, number literals, two's complement for negative numbers, bitwise and shift operators, and real-world applications with practical examples.
Last Updated
March 2026
Read Time
18 min
Level
Beginner to Intermediate
What is a Number System?
A number system is a mathematical framework for representing quantities using a fixed set of digits and a base (also called radix). The base determines how many unique digits are available and how positional value is assigned to each digit. Every position in a number represents a power of the base โ just like how the '3' in '300' means 3 ร 10ยฒ in decimal.
Computers โ including the JVM that runs Java programs โ operate entirely on binary (base 2): every piece of data, every instruction, every character in memory is ultimately represented as a sequence of bits (0s and 1s). As a Java developer, understanding number systems means understanding how the data you write in code (int x = 255) is actually stored and manipulated at the hardware level โ and how to work with that binary representation directly when needed.
Java natively supports four number systems in source code: decimal (base 10, everyday use), binary (base 2, bit-level operations), octal (base 8, legacy Unix permissions), and hexadecimal (base 16, memory addresses, colour codes, cryptographic hashes). All four compile to identical machine instructions โ they are simply different ways of writing the same integer value in source code.
Four Number Systems Supported in Java
Here is a concise overview of each number system Java supports, including its base, digit set, Java prefix, and primary use case:
public class NumberSystems {
public static void main(String[] args) {
// All four literals represent the same value: 255
int decimal = 255; // Decimal (base 10)
int binary = 0b11111111; // Binary (base 2) โ prefix 0b
int octal = 0377; // Octal (base 8) โ leading 0
int hexadecimal = 0xFF; // Hexadecimal (base 16) โ prefix 0x
System.out.println("Decimal : " + decimal);
System.out.println("Binary : " + binary);
System.out.println("Octal : " + octal);
System.out.println("Hexadecimal : " + hexadecimal);
// All are equal โ same bits in memory
System.out.println("All equal? : " + (decimal == binary && binary == octal && octal == hexadecimal));
// Java 7+ โ underscores in numeric literals for readability
int creditCard = 1234_5678_9012_3456; // decimal with underscores
int colorRed = 0xFF_00_00; // hex with underscores
int flags = 0b1010_0101; // binary with underscores
System.out.println("\nCredit card : " + creditCard);
System.out.println("Color Red : " + colorRed);
System.out.println("Flags byte : " + flags);
}
}Output
Decimal : 255 Binary : 255 Octal : 255 Hexadecimal : 255 All equal? : true Credit card : 1234567890123456 Color Red : 16711680 Flags byte : 165Why Programmers Need Number Systems
Understanding number systems is not academic theory โ it has direct, daily practical applications in professional Java development:
- โถ
๐จ Colour Codes and Graphics โ RGB colours in web and Android development are written in hexadecimal: #FF5733 means Red=0xFF (255), Green=0x57 (87), Blue=0x33 (51). Java AWT and Android's Color class accept hex values like 0xFF5733.
- โถ
๐ Cryptography and Hashing โ SHA-256, MD5, and other hash outputs are hex strings: e.g. 'a9993e36476...' Each hex character represents 4 bits (a nibble), making hex the most compact human-readable representation of byte arrays.
- โถ
๐ฉ Bit Flags and Permissions โ Linux file permissions (chmod 755 = rwxr-xr-x) are octal. Java's NIO FilePermissions, Android's Manifest permissions, and network flag fields use bit manipulation where understanding binary layout is essential.
- โถ
๐ง Memory and Pointer Arithmetic โ JVM memory addresses, object references in debugging output (e.g. Object@1b6d3586), and native memory operations via JNI or Java's Unsafe class all use hexadecimal.
- โถ
โ๏ธ Bitwise Operations for Performance โ Fast power-of-2 operations, bitmask flags, low-level protocol parsing (TCP headers, USB HID reports), and embedded systems interfaces all require direct binary manipulation.
- โถ
๐ข Binary Data Parsing โ Reading binary file formats (PNG, ZIP, class files), network packets, or hardware sensor data requires understanding how bytes (8 bits each) map to integer values across different bases.
Binary vs Octal vs Decimal vs Hexadecimal โ Full Comparison
Understanding how the same values look across all four bases builds the mental model needed for base conversion. Here is a reference table of values 0โ20 across all four systems:
Key insight: One hexadecimal digit represents exactly 4 binary bits (a nibble). One octal digit represents exactly 3 binary bits. This is why hex is so popular for representing bytes โ one byte (8 bits) is always exactly two hex digits (e.g., 0xFF = 1111 1111 = 255).
Number Literals in Java
Java allows integer literals to be written in all four bases directly in source code. Java 7 also added underscore separators inside numeric literals to improve readability โ the underscores are ignored by the compiler.
public class NumericLiterals {
public static void main(String[] args) {
// ---- INTEGER LITERALS ----
int dec = 1_000_000; // decimal โ 1 million
int bin = 0b0001_0000; // binary โ 16
int oct = 0755; // octal โ 493 (Unix rwxr-xr-x)
int hex = 0xCAFE_BABE; // hex โ Java class file magic number
// ---- LONG LITERALS (suffix L) ----
long bigDec = 9_876_543_210L;
long binLng = 0b1111_1111_1111_1111L; // 65535L
long hexLng = 0xDEAD_BEEF_CAFEL;
// ---- FLOAT LITERALS (suffix f) ----
float pi = 3.14_159_265f;
double dpi = 3.141_592_653_589_793;
// ---- SCIENTIFIC NOTATION ----
double avogadro = 6.022e23; // 6.022 ร 10^23
double electron = 1.6e-19; // 1.6 ร 10^-19
// ---- CHAR LITERALS (Unicode hex) ----
char rupee = '\u20B9'; // โน โ Unicode hex U+20B9
char omega = '\u03A9'; // ฮฉ
char check = '\u2713'; // โ
System.out.println("dec = " + dec);
System.out.println("bin (16) = " + bin);
System.out.println("oct (493) = " + oct);
System.out.printf ("hex magic = %X%n", hex);
System.out.println("bigDec = " + bigDec);
System.out.println("pi float = " + pi);
System.out.println("Avogadro = " + avogadro);
System.out.println("Rupee sym = " + rupee);
System.out.println("Check sym = " + check);
}
}Output
dec = 1000000 bin (16) = 16 oct (493) = 493 hex magic = CAFEBABE bigDec = 9876543210 pi float = 3.1415927 Avogadro = 6.022E23 Rupee sym = โน Check sym = โImportant rules for underscores in literals: Underscores cannot appear at the start or end of a literal (_255 and 255_ are invalid). They cannot appear adjacent to the decimal point in floating-point literals (3._14 is invalid). They cannot appear before the L, f, or d suffix. Other than these restrictions, underscores can appear anywhere โ including in hex, binary, and octal literals.
Java Built-in Conversion Methods
Java's Integer, Long, and String classes provide a complete set of built-in methods for converting between number bases. These are the fastest and most reliable way to perform base conversions in Java.
public class ConversionMethods {
public static void main(String[] args) {
int n = 173;
// Decimal โ Other bases
System.out.println("Decimal : " + n);
System.out.println("โ Binary : " + Integer.toBinaryString(n));
System.out.println("โ Octal : " + Integer.toOctalString(n));
System.out.println("โ Hexadecimal : " + Integer.toHexString(n));
System.out.println("โ Base 5 : " + Integer.toString(n, 5));
System.out.println("โ Base 36 : " + Integer.toString(n, 36));
// Other bases โ Decimal
System.out.println("\nBinary '10101101' โ Decimal: " + Integer.parseInt("10101101", 2));
System.out.println("Octal '255' โ Decimal: " + Integer.parseInt("255", 8));
System.out.println("Hex 'AD' โ Decimal: " + Integer.parseInt("AD", 16));
// Bit information
System.out.println("\nBit count of 173 : " + Integer.bitCount(n));
System.out.println("Leading zeros : " + Integer.numberOfLeadingZeros(n));
System.out.println("Trailing zeros : " + Integer.numberOfTrailingZeros(n));
System.out.println("Highest one bit : " + Integer.highestOneBit(n));
// Padded binary string (8-bit padding)
String padded = String.format("%8s", Integer.toBinaryString(n)).replace(" ", "0");
System.out.println("\nPadded binary (8-bit): " + padded);
// Padded hex string (4 digits)
System.out.printf("Padded hex (4-digit) : %04X%n", n);
}
}Output
Decimal : 173 โ Binary : 10101101 โ Octal : 255 โ Hexadecimal : ad โ Base 5 : 1143 โ Base 36 : 4t Binary '10101101' โ Decimal: 173 Octal '255' โ Decimal: 173 Hex 'AD' โ Decimal: 173 Bit count of 173 : 5 Leading zeros : 24 Trailing zeros : 0 Highest one bit : 128 Padded binary (8-bit): 10101101 Padded hex (4-digit) : 00ADManual Base Conversion Algorithms
Understanding the manual algorithms behind base conversion is essential for interviews and for understanding what Java's built-in methods do internally. Here are the three most common manual conversion algorithms:
public class ManualConversions {
// Algorithm 1: Decimal โ Binary (repeated division by 2)
static String decimalToBinary(int n) {
if (n == 0) return "0";
StringBuilder sb = new StringBuilder();
int temp = Math.abs(n);
while (temp > 0) {
sb.append(temp % 2); // remainder is 0 or 1
temp /= 2; // integer divide by base
}
if (n < 0) sb.append("-");
return sb.reverse().toString();
}
// Algorithm 2: Binary String โ Decimal (positional weight sum)
static int binaryToDecimal(String binary) {
int decimal = 0;
int power = 0;
for (int i = binary.length() - 1; i >= 0; i--) {
int bit = binary.charAt(i) - '0'; // '0'โ0, '1'โ1
decimal += bit * (int) Math.pow(2, power);
power++;
}
return decimal;
}
// Algorithm 3: Decimal โ Any Base (generalised)
static String decimalToBase(int n, int base) {
if (n == 0) return "0";
String digits = "0123456789ABCDEF";
StringBuilder sb = new StringBuilder();
int temp = Math.abs(n);
while (temp > 0) {
sb.append(digits.charAt(temp % base));
temp /= base;
}
if (n < 0) sb.append("-");
return sb.reverse().toString();
}
public static void main(String[] args) {
System.out.println("--- Decimal to Binary ---");
System.out.println("25 โ " + decimalToBinary(25));
System.out.println("100 โ " + decimalToBinary(100));
System.out.println("255 โ " + decimalToBinary(255));
System.out.println("\n--- Binary to Decimal ---");
System.out.println("11001 โ " + binaryToDecimal("11001"));
System.out.println("1100100 โ " + binaryToDecimal("1100100"));
System.out.println("11111111 โ " + binaryToDecimal("11111111"));
System.out.println("\n--- Decimal to Any Base ---");
System.out.println("255 base 2 โ " + decimalToBase(255, 2));
System.out.println("255 base 8 โ " + decimalToBase(255, 8));
System.out.println("255 base 16 โ " + decimalToBase(255, 16));
System.out.println("255 base 5 โ " + decimalToBase(255, 5));
}
}Output
--- Decimal to Binary --- 25 โ 11001 100 โ 1100100 255 โ 11111111 --- Binary to Decimal --- 11001 โ 25 1100100 โ 100 11111111 โ 255 --- Decimal to Any Base --- 255 base 2 โ 11111111 255 base 8 โ 377 255 base 16 โ FF 255 base 5 โ 2010Two's Complement โ How Java Represents Negative Numbers
Java's primitive integer types (byte, short, int, long) use two's complement binary representation for negative numbers. This is not just theory โ it explains exactly why Integer.MAX_VALUE + 1 == Integer.MIN_VALUE (integer overflow), and why Integer.toBinaryString(-1) returns 32 ones.
- โถ
Step 1 โ Write the binary of the absolute value โ For -25: write binary of 25 = 0001 1001 (8-bit)
- โถ
Step 2 โ Flip all bits (one's complement) โ 0001 1001 โ 1110 0110
- โถ
Step 3 โ Add 1 to the result โ 1110 0110 + 1 = 1110 0111 โ this is -25 in 8-bit two's complement
public class TwosComplement {
public static void main(String[] args) {
// Integer.toBinaryString shows the actual 32-bit two's complement
System.out.println("Binary of 5 : " + Integer.toBinaryString(5));
System.out.println("Binary of -5 : " + Integer.toBinaryString(-5));
System.out.println("Binary of 1 : " + Integer.toBinaryString(1));
System.out.println("Binary of -1 : " + Integer.toBinaryString(-1)); // 32 ones
System.out.println("Binary of 0 : " + Integer.toBinaryString(0));
// Two's complement property: n + (~n) = -1
int x = 42;
System.out.println("\nx = " + x);
System.out.println("~x (flip) = " + (~x));
System.out.println("x + (~x) = " + (x + (~x))); // always -1
System.out.println("-x manual = " + (~x + 1)); // two's complement
System.out.println("-x java = " + (-x)); // same result
// Integer overflow โ two's complement wrap-around
System.out.println("\nMAX_VALUE : " + Integer.MAX_VALUE);
System.out.println("MAX_VALUE + 1 : " + (Integer.MAX_VALUE + 1)); // wraps to MIN_VALUE
System.out.println("MIN_VALUE : " + Integer.MIN_VALUE);
System.out.println("MIN_VALUE - 1 : " + (Integer.MIN_VALUE - 1)); // wraps to MAX_VALUE
// Bit widths of Java integer types
System.out.println("\nbyte range: " + Byte.MIN_VALUE + " to " + Byte.MAX_VALUE);
System.out.println("short range: " + Short.MIN_VALUE + " to " + Short.MAX_VALUE);
System.out.println("int range: " + Integer.MIN_VALUE + " to " + Integer.MAX_VALUE);
System.out.println("long range: " + Long.MIN_VALUE + " to " + Long.MAX_VALUE);
}
}Output
Binary of 5 : 101 Binary of -5 : 11111111111111111111111111111011 Binary of 1 : 1 Binary of -1 : 11111111111111111111111111111111 Binary of 0 : 0 x = 42 ~x (flip) = -43 x + (~x) = -1 -x manual = -42 -x java = -42 MAX_VALUE : 2147483647 MAX_VALUE + 1 : -2147483648 MIN_VALUE : -2147483648 MIN_VALUE - 1 : 2147483647 byte range: -128 to 127 short range: -32768 to 32767 int range: -2147483648 to 2147483647 long range: -9223372036854775808 to 9223372036854775807Bitwise Operators in Java
Java provides six bitwise operators that operate on individual bits of integer operands. These are fundamental for bit manipulation, flag management, performance optimisation, and low-level data processing.
public class BitwiseDemo {
public static void main(String[] args) {
int a = 0b1010_1100; // 172
int b = 0b0011_1111; // 63
System.out.printf("a = %3d | %s%n", a, Integer.toBinaryString(a));
System.out.printf("b = %3d | %s%n", b, Integer.toBinaryString(b));
System.out.printf("a & b = %3d | %s%n", (a&b), Integer.toBinaryString(a&b));
System.out.printf("a | b = %3d | %s%n", (a|b), Integer.toBinaryString(a|b));
System.out.printf("a ^ b = %3d | %s%n", (a^b), Integer.toBinaryString(a^b));
System.out.printf("~a = %3d | (32-bit two's complement)%n", ~a);
System.out.println();
// Common bitwise tricks
int x = 52;
System.out.println("--- Bitwise Tricks ---");
System.out.println("x = " + x + " binary: " + Integer.toBinaryString(x));
// Check if even or odd
System.out.println("Is even? : " + ((x & 1) == 0)); // LSB = 0 โ even
// Multiply and divide by 2
System.out.println("x << 1 (ร2) = " + (x << 1)); // 104
System.out.println("x >> 1 (รท2) = " + (x >> 1)); // 26
System.out.println("x << 3 (ร8) = " + (x << 3)); // 416
// Check if power of 2
int p = 64;
System.out.println(p + " is power of 2? " + ((p & (p - 1)) == 0));
// Toggle, set, clear a specific bit
int flags = 0b0000_0000;
flags |= (1 << 3); // SET bit 3
System.out.println("After SET bit 3: " + Integer.toBinaryString(flags));
flags ^= (1 << 3); // TOGGLE bit 3
System.out.println("After TOGGLE bit 3: " + Integer.toBinaryString(flags));
flags |= (1 << 5); // SET bit 5
flags &= ~(1 << 5); // CLEAR bit 5
System.out.println("After CLEAR bit 5: " + Integer.toBinaryString(flags));
}
}Output
a = 172 | 10101100 b = 63 | 111111 a & b = 44 | 101100 a | b = 191 | 10111111 a ^ b = 147 | 10010011 ~a = -173 | (32-bit two's complement) --- Bitwise Tricks --- x = 52 binary: 110100 Is even? : true x << 1 (ร2) = 104 x >> 1 (รท2) = 26 x << 3 (ร8) = 416 64 is power of 2? true After SET bit 3: 1000 After TOGGLE bit 3: 0 After CLEAR bit 5: 0Decimal to Binary Conversion โ Step-by-Step Flow
The flowchart below illustrates the classic repeated division by 2 algorithm for converting a decimal integer to its binary representation โ the same algorithm used by Integer.toBinaryString() internally.
Code Execution Flow โ from source to output
Trace for N = 25: 25 รท 2 = 12 remainder 1 โ 12 รท 2 = 6 remainder 0 โ 6 รท 2 = 3 remainder 0 โ 3 รท 2 = 1 remainder 1 โ 1 รท 2 = 0 remainder 1. Remainders read bottom-to-top: 11001. Verify: 1ร16 + 1ร8 + 0ร4 + 0ร2 + 1ร1 = 25 โ
Bit Shift Operators โ << >> >>>
Java's three shift operators move all bits of an integer left or right by a specified number of positions. They are equivalent to fast multiplication or division by powers of 2 and are heavily used in hashing, encoding, and performance-critical code.
public class ShiftOperators {
public static void main(String[] args) {
int n = 12; // binary: 0000 1100
System.out.println("n = " + n + " binary: " + Integer.toBinaryString(n));
// Left shift << : multiply by 2^k (fast power-of-2 multiplication)
System.out.println("\n--- Left Shift (<<) ---");
System.out.println("n << 1 = " + (n << 1) + " (12 ร 2 = 24)");
System.out.println("n << 2 = " + (n << 2) + " (12 ร 4 = 48)");
System.out.println("n << 3 = " + (n << 3) + " (12 ร 8 = 96)");
// Signed right shift >> : divide by 2^k (preserves sign)
System.out.println("\n--- Signed Right Shift (>>) ---");
System.out.println("n >> 1 = " + (n >> 1) + " (12 รท 2 = 6)");
System.out.println("n >> 2 = " + (n >> 2) + " (12 รท 4 = 3)");
int neg = -48;
System.out.println("\n-48 >> 1 = " + (neg >> 1) + " (-48 รท 2 = -24, sign preserved)");
System.out.println("-48 >> 2 = " + (neg >> 2) + " (-48 รท 4 = -12, sign preserved)");
// Unsigned right shift >>> : always fills with 0 (ignores sign)
System.out.println("\n--- Unsigned Right Shift (>>>) ---");
System.out.println("-48 >>> 1 = " + (-48 >>> 1) + " (large positive โ sign bit โ 0)");
System.out.println("-1 >>> 1 = " + (-1 >>> 1) + " (Integer.MAX_VALUE = 2147483647)");
// Real-world: HashMap's hash spreading uses >>>
// hash(key) = key.hashCode() ^ (key.hashCode() >>> 16)
int hashCode = 0xABCD1234;
int spread = hashCode ^ (hashCode >>> 16);
System.out.printf("%nHashMap hash spread: 0x%X ^ 0x%X = 0x%X%n",
hashCode, hashCode >>> 16, spread);
// Mid-point without overflow โ used in binary search
int lo = 1_000_000_000, hi = 2_000_000_000;
int mid = (lo + hi) >>> 1; // safe โ no overflow
System.out.println("\nSafe mid (no overflow): " + mid);
}
}Output
n = 12 binary: 1100 --- Left Shift (<<) --- n << 1 = 24 (12 ร 2 = 24) n << 2 = 48 (12 ร 4 = 48) n << 3 = 96 (12 ร 8 = 96) --- Signed Right Shift (>>) --- n >> 1 = 6 (12 รท 2 = 6) n >> 2 = 3 (12 รท 4 = 3) -48 >> 1 = -24 (-48 รท 2 = -24, sign preserved) -48 >> 2 = -12 (-48 รท 4 = -12, sign preserved) --- Unsigned Right Shift (>>>) --- -48 >>> 1 = 2147483624 (large positive โ sign bit โ 0) -1 >>> 1 = 2147483647 (Integer.MAX_VALUE = 2147483647) HashMap hash spread: 0xABCD1234 ^ 0xABCD = 0xABCD9889 Safe mid (no overflow): 1500000000Number Formatting and Display
Java's String.format() and printf() provide powerful format specifiers for displaying numbers in any base and with custom padding, making output clean and professional.
public class NumberFormatting {
public static void main(String[] args) {
int[] values = {0, 7, 15, 42, 100, 173, 255};
System.out.printf("%-10s %-10s %-10s %-12s%n",
"Decimal", "Binary", "Octal", "Hexadecimal");
System.out.println("-".repeat(45));
for (int v : values) {
System.out.printf("%-10d %-10s %-10o %-12X%n",
v,
String.format("%8s", Integer.toBinaryString(v)).replace(" ","0"),
v,
v);
}
System.out.println();
// Format specifier summary
int n = 255;
System.out.println("--- Format Specifiers ---");
System.out.printf("%d โ decimal%n", n);
System.out.printf("%o โ octal%n", n);
System.out.printf("%x โ hex lowercase%n", n);
System.out.printf("%X โ hex uppercase%n", n);
System.out.printf("%08X โ padded hex (8 digits)%n", n);
System.out.printf("#%06X โ hex colour code%n", n);
System.out.printf("%+d โ with sign%n", n);
System.out.printf("%,d โ with commas%n", 1_000_000);
System.out.printf("%.4f โ 4 decimal places%n", Math.PI);
System.out.printf("%e โ scientific notation%n", 1234567.89);
}
}Output
Decimal Binary Octal Hexadecimal --------------------------------------------- 0 00000000 0 0 7 00000111 7 7 15 00001111 17 F 42 00101010 52 2A 100 01100100 144 64 173 10101101 255 AD 255 11111111 377 FF --- Format Specifiers --- 255 โ decimal 377 โ octal ff โ hex lowercase FF โ hex uppercase 000000FF โ padded hex (8 digits) #0000FF โ hex colour code +255 โ with sign 1,000,000 โ with commas 3.1416 โ 4 decimal places 1.234568e+06 โ scientific notationBest Practices for Java Number Systems
Professional Java developers follow these best practices to write clear, correct, and portable code when working with number systems and bit manipulation:
- โถ
โ 1. Use Binary Literals for Bit Flags and Masks โ When defining bit masks or flags, write them in binary (0b1000_0000) not decimal (128) or hex (0x80). Binary literals make the bit structure immediately visible without mental translation.
- โถ
โ 2. Use Hex for Byte Values and Colour Codes โ One byte (8 bits) = two hex digits. Use 0xFF not 255 when working with byte arrays, colour components, or protocol fields. Hex communicates byte boundaries clearly.
- โถ
โ 3. Use Underscore Separators for Large Literals โ Write 1_000_000 not 1000000, 0xFF_FF not 0xFFFF, and 0b1010_0101 not 0b10100101. Underscores dramatically improve readability for constants, bitmasks, and large numbers.
- โถ
โ 4. Use >>> Instead of >> for Unsigned Operations โ When shifting for bit extraction or hash computation (not arithmetic division), use >>> to avoid accidental sign extension. >>> always fills with 0; >> extends the sign bit. Java's HashMap uses >>> 16 in its hash spreading โ not >>.
- โถ
โ 5. Prefer Integer.toBinaryString() Over Manual Loops โ Java's built-in Integer.toBinaryString(), Integer.toHexString(), and Integer.parseInt(s, radix) are faster, tested, and handles edge cases (0, negative values) correctly. Use manual algorithms only in interviews or when custom formatting is needed.
- โถ
โ 6. Be Aware of Integer Overflow in Bit Operations โ Left-shifting a value past the sign bit causes overflow. int max = Integer.MAX_VALUE; max << 1; wraps around. For values that might overflow, use long literals and Long arithmetic, or check bounds before shifting.
- โถ
โ 7. Use EnumSet Instead of int Bitmasks for Flags in Production โ While int bitmasks are fast and concise, EnumSet<MyFlags> provides type safety, readable names, and efficient bit operations under the hood. Prefer EnumSet for domain flag management in production Java code.
- โถ
โ 8. Never Use Octal Literals for Non-Permission Values โ A leading zero on an integer literal makes it octal: int x = 010 means 8, not 10! This is a notorious Java gotcha. Only use octal literals intentionally for file permission constants. Never write leading-zero decimal numbers.
Real-World Code Examples
Example 1 โ RGB Colour Encoder/Decoder
public class RGBColour {
// Pack R, G, B components into a single 32-bit int
static int encode(int r, int g, int b) {
return (r << 16) | (g << 8) | b;
}
// Extract components using bit masks
static int getRed(int colour) {
return (colour >> 16) & 0xFF;
}
static int getGreen(int colour) {
return (colour >> 8) & 0xFF;
}
static int getBlue(int colour) {
return colour & 0xFF;
}
static String toHexCode(int colour) {
return String.format("#%06X", colour & 0xFFFFFF);
}
public static void main(String[] args) {
// Encode colours
int tomato = encode(255, 99, 71);
int steelBlue = encode(70, 130, 180);
int gold = encode(255, 215, 0);
// Display colour info
int[] colours = {tomato, steelBlue, gold};
String[] names = {"Tomato", "SteelBlue", "Gold"};
System.out.printf("%-12s %-10s R G B%n", "Name", "HexCode");
System.out.println("-".repeat(40));
for (int i = 0; i < colours.length; i++) {
System.out.printf("%-12s %-10s %-4d %-4d %d%n",
names[i],
toHexCode(colours[i]),
getRed(colours[i]),
getGreen(colours[i]),
getBlue(colours[i]));
}
// Decode a hex colour code
int parsed = Integer.parseInt("4169E1", 16); // RoyalBlue
System.out.printf("%nRoyalBlue #4169E1 โ R=%d G=%d B=%d%n",
getRed(parsed), getGreen(parsed), getBlue(parsed));
}
}Output
Name HexCode R G B ---------------------------------------- Tomato #FF6347 255 99 71 SteelBlue #4682B4 70 130 180 Gold #FFD700 255 215 0 RoyalBlue #4169E1 โ R=65 G=105 B=225Example 2 โ Permission Flags Using Bitmask
public class PermissionFlags {
// Permission constants โ each is a distinct bit
static final int READ = 0b0001; // bit 0 = 1
static final int WRITE = 0b0010; // bit 1 = 2
static final int EXECUTE = 0b0100; // bit 2 = 4
static final int DELETE = 0b1000; // bit 3 = 8
static final int ADMIN = 0b1111; // all permissions
// Check if a permission is set
static boolean hasPermission(int userPerms, int flag) {
return (userPerms & flag) != 0;
}
// Grant a permission
static int grant(int userPerms, int flag) {
return userPerms | flag;
}
// Revoke a permission
static int revoke(int userPerms, int flag) {
return userPerms & ~flag;
}
static void printPermissions(String user, int perms) {
System.out.printf("%-10s [%04d] READ:%-5b WRITE:%-5b EXEC:%-5b DEL:%b%n",
user,
Integer.parseInt(Integer.toBinaryString(perms)),
hasPermission(perms, READ),
hasPermission(perms, WRITE),
hasPermission(perms, EXECUTE),
hasPermission(perms, DELETE));
}
public static void main(String[] args) {
int arjun = READ | WRITE; // 0011 = 3
int priya = READ | EXECUTE; // 0101 = 5
int admin = ADMIN; // 1111 = 15
System.out.println("Initial Permissions:");
printPermissions("Arjun", arjun);
printPermissions("Priya", priya);
printPermissions("Admin", admin);
arjun = grant(arjun, EXECUTE); // add execute
priya = revoke(priya, READ); // remove read
System.out.println("\nAfter Updates:");
printPermissions("Arjun", arjun);
printPermissions("Priya", priya);
}
}Output
Initial Permissions: Arjun [0011] READ:true WRITE:true EXEC:false DEL:false Priya [0101] READ:true WRITE:false EXEC:true DEL:false Admin [1111] READ:true WRITE:true EXEC:true DEL:true After Updates: Arjun [0111] READ:true WRITE:true EXEC:true DEL:false Priya [0100] READ:false WRITE:false EXEC:true DEL:falsePractice This Code โ Live Editor
Advantages and Disadvantages of Working with Number Systems in Java
Understanding and using multiple number systems in Java brings concrete benefits โ but also requires careful handling to avoid subtle bugs.
Java Number System โ Interview Questions
These are the most frequently asked interview questions on the Java Number System and related bit manipulation for Java developer and competitive programming interviews.
Practice Questions โ Test Your Knowledge
Test your understanding of Java Number Systems with these practice questions. Attempt each before revealing the answer.
1. What are the decimal values of: (a) 0b1010 (b) 0777 (c) 0x1F (d) 0b1111_0000?
Easy2. What is the output? int x = 0b1010; // 10 int y = 0b1100; // 12 System.out.println(x & y); // AND System.out.println(x | y); // OR System.out.println(x ^ y); // XOR
Easy3. Why does int x = 09; cause a compile error but int y = 07; does not?
Easy4. Write a Java expression to extract the lower byte (bits 0โ7) and upper byte (bits 8โ15) of an int using bitwise operators.
Medium5. What does n & (n-1) compute? What is it useful for?
Medium6. What is the output of Integer.toBinaryString(-5) and why does it have 32 characters?
Medium7. A 32-bit int stores an RGBA colour as: bits 31-24 = Alpha, bits 23-16 = Red, bits 15-8 = Green, bits 7-0 = Blue. Write expressions to extract each component.
Hard8. Without using any division operator (/) or modulo (%), determine if an integer n is even or odd using bitwise operations. Explain why it works.
EasyConclusion โ Mastering Java Number Systems
The number system is the bedrock of computer science โ and Java's first-class support for binary, octal, decimal, and hexadecimal literals, combined with its rich Integer utility methods and bitwise operator set, gives you every tool needed to work directly at the bit level when required.
Mastering number systems in Java means knowing when to use binary literals for bit flags, hexadecimal for byte values and colour codes, and underscore separators for readable constants. It means understanding two's complement to predict overflow behaviour, using >>> correctly for unsigned shifts, and leveraging bit tricks like n & (n-1) for high-performance operations in competitive programming and systems code.
Your next steps: explore Java's Byte and ByteBuffer classes for binary data I/O; study IEEE 754 floating-point representation to understand how float and double store fractional binary numbers; learn Java's BigInteger for arbitrary-precision arithmetic and base conversion of very large numbers; and see how bit manipulation powers Java's HashMap.hash(), UUID generation, and cryptographic operations in production systems.
Remember: Binary (0b) for flags, Hex (0x) for bytes, underscore separators for readability, >>> for unsigned shifts, and always name your bit constants. These five habits will keep your number system code correct, readable, and professional. โ