2.2 Primitive Types: Ranges and Limits
Prerequisites: Variables, Assignment, and Scope
Estimated time: 30 minutes
You are ready to continue when: You can choose the appropriate type for integers, floats, UTF-16 code units, and boolean values
Four Integer Types
| Type | Bit Count | Minimum Value | Maximum Value | Common Uses |
|---|---|---|---|---|
byte | 8 | -128 | 127 | Raw byte data, compact arrays, protocol fields |
short | 16 | -32,768 | 32,767 | Less commonly used narrow integer data |
int | 32 | -2³¹ | 2³¹ - 1 | Default integer choice, indexing, counting |
long | 64 | -2⁶³ | 2⁶³ - 1 | Integers outside the int range |
The Java specification fixes these value ranges and they do not vary with the CPU bit count. The specific storage layout of variables in objects, arrays, stack frames, or registers is part of the JVM implementation and runtime optimization, and cannot be deduced solely from the bit count in the table.
public class IntegerTypes {
public static void main(String[] args) {
byte small = 100;
short port = 30_000;
int population = 1_000_000;
long distance = 3_000_000_000L;
System.out.println(Byte.MIN_VALUE + ".." + Byte.MAX_VALUE);
System.out.println(Integer.MIN_VALUE + ".." + Integer.MAX_VALUE);
System.out.println(distance);
}
}Numbers larger than int that are in decimal form require the L suffix. Prefer uppercase L to avoid confusion with the lowercase l and the number 1.
Integer Overflow Wraps Around
int max = Integer.MAX_VALUE;
System.out.println(max);
System.out.println(max + 1);Result:
2147483647
-2147483648Java's standard arithmetic operations for integer addition, subtraction, and multiplication retain the lower bits of the fixed width, resulting in binary two's complement wrap-around. It does not automatically upgrade to long, nor does it automatically throw an exception on overflow. When detection is needed, use:
int checked = Math.addExact(Integer.MAX_VALUE, 1);This will throw ArithmeticException. Switching to long only expands the range and does not eliminate the possibility of overflow; still, the business boundary should be considered when choosing the verification strategy.
float and double
| Type | Bit Size | Approximately Decimal Significant Digits | Default Literal |
|---|---|---|---|
float | 32 | 6–7 digits | Requires F suffix |
double | 64 | 15–16 digits | Decimal floating-point literals default to this type |
float ratio = 0.5F;
double temperature = 21.5;Binary floating-point numbers can only accurately represent a subset of decimal fractions:
double sum = 0.1 + 0.2;
System.out.println(sum);
System.out.println(sum == 0.3);Typical Output:
0.30000000000000004
falseWhen comparing measurements, it's common to use a tolerance that matches the scale of the problem rather than applying a fixed "universal epsilon." When precise adherence to decimal currency and rounding rules is required, it's typically done using BigDecimal or an explicitly designed smallest currency unit integer:
import java.math.BigDecimal;
BigDecimal price = new BigDecimal("0.10");
BigDecimal tax = new BigDecimal("0.20");
System.out.println(price.add(tax)); // 0.30Using string constructors allows objects to be built with the exact decimal value written; new BigDecimal(0.1) will bring in an approximation of the binary double.
Floating-point types also include positive infinity, negative infinity, and NaN. For example, dividing a floating-point number by 0.0 typically results in infinity or NaN, which is different from integer division by zero, which throws ArithmeticException.
char is a UTF-16 Code Unit
char grade = 'A';
System.out.println((int) grade); // 65The value of char ranges from 0 to 65,535, corresponding to a single UTF-16 code unit. It does not guarantee that it represents a complete Unicode character: code points outside the Basic Multilingual Plane require a pair of surrogate units, which are two char.
String symbol = "😀";
System.out.println(symbol.length()); // 2 UTF-16 code units
System.out.println(symbol.codePointCount(0, symbol.length())); // 1 code pointTherefore, the statement "one char equals one character as seen by the user" is unreliable. Even a Unicode code point does not necessarily equal a user-perceived grapheme cluster. When processing natural language text, prioritize using String and appropriate APIs such as code point processing and segmenters.
Single quotes delimit a char literal; double quotes delimit a String literal:
char letter = 'A';
String word = "A";The Language Boundary of boolean
boolean ready = true;
boolean finished = false;The Java language only allows true and false. It does not permit integers to be treated as boolean values:
// boolean ready = 1; // Compilation errorThe Java Language Specification does not define that a single boolean variable must occupy 1 bit or 1 byte. The size of fields, arrays, and JVM internal representations is determined by the specification and implementation at different levels. Tutorials should not assign a fictional fixed size to it.
Integer Division and Remainders
System.out.println(5 / 2); // 2
System.out.println(5 % 2); // 1
System.out.println(5 / 2.0); // 2.5
System.out.println((double) 5 / 2); // 2.5When two integer operands are involved, integer division is performed, and the result is truncated toward zero. If at least one operand is a floating-point type, the other is promoted numerically, and a floating-point division is executed.
Field Default Values and Local Variables Differ
Class fields and array elements are initialized to their type's default value: integers and char are zero, floats are positive zero, boolean is false, and references are null. Method local variables must be explicitly assigned before they can be read.
public class Defaults {
static int fieldCount; // Default 0
public static void main(String[] args) {
int[] values = new int[2]; // Element default 0
int localCount;
System.out.println(fieldCount);
System.out.println(values[0]);
// System.out.println(localCount); // Compilation error
}
}Python vs C++ Comparison
Python's standard int supports arbitrary precision, but is still limited by available memory and implementation; Python's float is typically IEEE 754 double-precision, leading to 0.1 + 0.2 representation errors. Python does not have a separate char type, and a text of length 1 is still considered a string.
C++'s basic integer types have minimum ranges defined by the standard, with actual widths depending on implementation and platform; sizeof(char) is fixed at 1, but the number of bits in a byte is determined by CHAR_BIT. C++ supports unsigned integers, whereas Java’s byte, short, int, and long are signed; char is an unsigned 16-bit integer type. The standard library also provides some unsigned arithmetic APIs.
Professional Quick Reference
| Scenario | Recommendation |
|---|---|
| General integers | Start with int, and upgrade to a larger type based on validated range |
| Large integers | long; consider BigInteger if the value exceeds its range |
| Scientific or measurement calculations | Typically double, with explicit error modeling |
| Exact decimal business rules | BigDecimal or a carefully designed fixed-point integer |
| Unicode text | String; explicitly define code units, code points, and grapheme clusters |
| Detecting integer overflow | Exact methods like Math.addExact or pre-validation |
Before Moving On
If you can only remember the boundaries, remember these five: long will still overflow; double cannot represent every decimal fraction exactly; char is a UTF-16 code unit; Java does not guarantee a fixed storage size for a single boolean; the initialization rules for fields, array elements, and local variables differ.
The next lesson covers moving between types.
→ Next: Numeric Conversion, Promotion, and Precision
Specification: JLS §4.2: Primitive Types and Values, §4.12.5: Initial Values of Variables.