Skip to content

VOL 01 / CH 02 / LESSON 02

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 ​

TypeBit CountMinimum ValueMaximum ValueCommon Uses
byte8-128127Raw byte data, compact arrays, protocol fields
short16-32,76832,767Less commonly used narrow integer data
int32-2³¹2³¹ - 1Default integer choice, indexing, counting
long64-2⁶³2⁶³ - 1Integers 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.

java
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 ​

java
int max = Integer.MAX_VALUE;
System.out.println(max);
System.out.println(max + 1);

Result:

text
2147483647
-2147483648

Java'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:

java
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 ​

TypeBit SizeApproximately Decimal Significant DigitsDefault Literal
float326–7 digitsRequires F suffix
double6415–16 digitsDecimal floating-point literals default to this type
java
float ratio = 0.5F;
double temperature = 21.5;

Binary floating-point numbers can only accurately represent a subset of decimal fractions:

java
double sum = 0.1 + 0.2;
System.out.println(sum);
System.out.println(sum == 0.3);

Typical Output:

text
0.30000000000000004
false

When 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:

java
import java.math.BigDecimal;

BigDecimal price = new BigDecimal("0.10");
BigDecimal tax = new BigDecimal("0.20");
System.out.println(price.add(tax)); // 0.30

Using 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 ​

java
char grade = 'A';
System.out.println((int) grade); // 65

The 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.

java
String symbol = "😀";
System.out.println(symbol.length());             // 2 UTF-16 code units
System.out.println(symbol.codePointCount(0, symbol.length())); // 1 code point

Therefore, 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:

java
char letter = 'A';
String word = "A";

The Language Boundary of boolean ​

java
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:

java
// boolean ready = 1; // Compilation error

The 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 ​

java
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.5

When 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.

java
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 ​

ScenarioRecommendation
General integersStart with int, and upgrade to a larger type based on validated range
Large integerslong; consider BigInteger if the value exceeds its range
Scientific or measurement calculationsTypically double, with explicit error modeling
Exact decimal business rulesBigDecimal or a carefully designed fixed-point integer
Unicode textString; explicitly define code units, code points, and grapheme clusters
Detecting integer overflowExact 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.

Built with VitePress | Software Systems Atlas