JB Header

Java Primitive Data Types and Their Ranges with Examples

Introduction Every variable in Java has a type, and the most basic types are the eight primitive data types. This tutorial explains Java's primitive data types and their ranges with examples. We will start with the difference between primitive types and reference types. We will then look at each group of primitives - the four integer types, the two floating-point types, char and boolean - with their sizes and ranges. Next we will print the exact ranges from Java itself, and see what happens when a value goes past the end of its range. Lastly, we will look at default values and how to choose the right type.

(Note - If you are new to variables, read Variables in JavaClick to read tutorial: Variables in Java: Declaration, Initialization and Scope first.) Primitive types vs reference types Java has two kinds of types -
  • Primitive types: The eight basic types built into the language - byte, short, int, long, float, double, char and boolean. A primitive variable holds its value directly. Their names are keywords, all in lower case.
  • Reference types: Classes, interfaces, arrays and so on - such as String, LocalDate or your own classes. A reference variable holds a reference to an object stored elsewhere in memory, or null.
Primitives are fast and use little memory, which is why Java uses them for numbers, characters and true/false values. Each primitive also has a matching class, such as Integer for int, called a wrapper classClick to read tutorial on Java Wrapper Classes. The eight primitive types at a glance
TypeSizeRangeDefaultExample
byte8 bits-128 to 1270byte b = 100;
short16 bits-32,768 to 32,7670short s = 30000;
int32 bitsabout -2.1 billion to 2.1 billion0int count = 42;
long64 bitsabout -9.2 × 1018 to 9.2 × 10180Llong views = 8_000_000_000L;
float32 bitsabout ±3.4 × 1038, 6-7 significant digits0.0ffloat f = 3.14f;
double64 bitsabout ±1.8 × 10308, 15-16 significant digits0.0double d = 3.14159;
char16 bits'\u0000' to '￿' (0 to 65,535)'\u0000'char grade = 'A';
boolean-true or falsefalseboolean done = true;

Unlike in some languages, these sizes are the same on every platform - an int is always 32 bits, whether the program runs on Windows, Linux or a phone.
Integer types - byte, short, int and long The four integer types hold whole numbers, positive or negative, and differ only in their size and range.
  • int is the default choice for whole numbers. A number written in code, such as 42, is an int.
  • long is for values too big for an int - such as populations, file sizes or time in milliseconds. A long value needs an L at the end: 8_000_000_000L.
  • byte and short save memory in large arrays, and byte is used for raw binary data such as file contents. They are rarely used for ordinary variables.
Floating-point types - float and double float and double hold numbers with a fractional part, such as 3.14. double is the default choice: it has about twice the precision of float, and a decimal number written in code is a double. A float value needs an f at the end: 3.14f.

Note - Floating-point numbers are stored in binary, so most decimal fractions, such as 0.1, cannot be stored exactly. Small rounding errors are normal, as the example below shows. Never use float or double for money - use java.math.BigDecimal, or count in cents with a long. char and boolean
  • char: Holds a single character, such as 'A' or '7', in single quotes. Internally it is a 16-bit unsigned number - the character's Unicode code - so a char can be used in arithmetic. 'A' is 65.
  • boolean: Holds true or false. It is the result of comparisons such as age >= 18, and controls if statements and loops. Unlike in C, a boolean is not a number - you cannot use 0 and 1 in its place.
Printing the exact ranges Each wrapper class has constants holding the range of its primitive type. Let us print them, and try out each type.
Printing the ranges of the primitive types
//PrimitiveRanges.java
public class PrimitiveRanges {
  public static void main(String[] args) {
    System.out.println("byte   : " + Byte.MIN_VALUE + " to " + Byte.MAX_VALUE);
    System.out.println("short  : " + Short.MIN_VALUE + " to " + Short.MAX_VALUE);
    System.out.println("int    : " + Integer.MIN_VALUE + " to " + Integer.MAX_VALUE);
    System.out.println("long   : " + Long.MIN_VALUE + " to " + Long.MAX_VALUE);
    System.out.println("float  : " + Float.MIN_VALUE + " to " + Float.MAX_VALUE);
    System.out.println("double : " + Double.MIN_VALUE + " to " + Double.MAX_VALUE);
    System.out.println("char   : " + (int) Character.MIN_VALUE + " to " + (int) Character.MAX_VALUE);

    char grade = 'A';
    System.out.println("grade = " + grade + ", grade + 1 = " + (grade + 1) + ", next char = " + (char) (grade + 1));
    System.out.println("0.1 + 0.2 = " + (0.1 + 0.2));
    System.out.println("float 1/3  = " + (1.0f / 3) + ", double 1/3 = " + (1.0 / 3));
  }
}
 OUTPUT of the above code
byte   : -128 to 127
short  : -32768 to 32767
int    : -2147483648 to 2147483647
long   : -9223372036854775808 to 9223372036854775807
float  : 1.4E-45 to 3.4028235E38
double : 4.9E-324 to 1.7976931348623157E308
char   : 0 to 65535
grade = A, grade + 1 = 66, next char = B
0.1 + 0.2 = 0.30000000000000004
float 1/3  = 0.33333334, double 1/3 = 0.3333333333333333
Explanation of the code
  • Float.MIN_VALUE and Double.MIN_VALUE are not the most negative values - they are the smallest positive values the types can hold. The most negative values are -Float.MAX_VALUE and -Double.MAX_VALUE.
  • grade + 1 is 66, because a char takes part in arithmetic as its Unicode number. Casting the result back with (char) gives the next letter, B. CastingClick to read tutorial: Type Conversion and Casting in Java with Examples is covered in its own tutorial.
  • 0.1 + 0.2 prints 0.30000000000000004 - the floating-point rounding error mentioned above.
  • 1.0f / 3 keeps about 7 digits, while 1.0 / 3 keeps about 16, which shows the difference in precision between float and double.
Overflow - going past the end of the range What happens when a calculation produces a value too big for its type? For integer types, Java does not report an error. The value silently overflows and wraps around to the other end of the range.
Integer overflow
//OverflowDemo.java
public class OverflowDemo {
  public static void main(String[] args) {
    int max = Integer.MAX_VALUE;
    System.out.println("max     = " + max);
    System.out.println("max + 1 = " + (max + 1));

    int millisPerYear = 1000 * 60 * 60 * 24 * 365;         // overflows int
    long millisPerYearOk = 1000L * 60 * 60 * 24 * 365;     // calculated as long
    System.out.println("int  : " + millisPerYear);
    System.out.println("long : " + millisPerYearOk);

    System.out.println("Math.addExact: " + Math.addExact(max, 1));
  }
}
 OUTPUT of the above code
max     = 2147483647
max + 1 = -2147483648
int  : 1471228928
long : 31536000000
Exception in thread "main" java.lang.ArithmeticException: integer overflow
	at java.base/java.lang.Math.addExact(Math.java:914)
	at OverflowDemo.main(OverflowDemo.java:13)
Explanation of the code
  • Integer.MAX_VALUE + 1 wraps around to Integer.MIN_VALUE, a large negative number.
  • The number of milliseconds in a year is about 31.5 billion, more than an int can hold. Even though it looks harmless, 1000 * 60 * 60 * 24 * 365 is calculated with ints and overflows. Writing the first number as 1000L makes the whole calculation use long, giving the correct answer.
  • When overflow would be a bug, use Math.addExact(), Math.multiplyExact() and similar methods. Instead of wrapping around, they throw an ArithmeticException, as the last line shows.
Default values and choosing a type Fields of a class which are not initialized get the default values shown in the table above - zero for the numeric types, '\u0000' for char and false for boolean. Local variables get no default and must be initialized before use. When choosing a type -
  • Use int for whole numbers, and long when the values can exceed about 2 billion.
  • Use double for decimal numbers in calculations, and BigDecimal for money.
  • Use boolean for yes/no values, and char for single characters. For text, use String, which is a class, not a primitive.
Summary In this tutorial we first saw the difference between primitive types, which hold their values directly, and reference types. We then looked at the eight primitive types with their sizes, ranges and defaults - the integer types byte, short, int and long, the floating-point types float and double, and char and boolean. Next we printed the exact ranges and saw floating-point rounding in action. We then saw how integer overflow silently wraps around, and how long and Math.addExact() help. Lastly, we went through how to choose the right type. In the next tutorial, we will look at literalsClick to read tutorial: Java Literals: Integer, Floating-Point, char and boolean - the way values of these types are written in code.