Java — Data Types
Two categories of types
Java divides all data into two groups:
- Primitive types — simple, built-in values (numbers, characters, booleans)
- Reference types — objects created from classes (Strings, arrays, custom classes)
Primitives store actual values. References store addresses that point to objects in memory.
Primitive types
Java has exactly 8 primitive types:
| Type | Size | Range / Purpose |
|---|---|---|
byte | 1 byte | -128 to 127 |
short | 2 bytes | -32,768 to 32,767 |
int | 4 bytes | -2 billion to 2 billion |
long | 8 bytes | extremely large integers |
float | 4 bytes | decimal numbers (6–7 digit precision) |
double | 8 bytes | decimal numbers (15 digit precision) |
char | 2 bytes | single Unicode character |
boolean | 1 bit | true or false |
Most of the time you'll use int, double, char, and boolean. The others exist for memory optimization in large datasets.
Choosing the right integer type
byte temperature = -40; // temperature rarely exceeds this range
short worldPopulation = 0; // too small — use int or long
int countryPopulation = 331000000;
long worldPopulationLong = 7_800_000_000L;
The L suffix marks a long literal. Without it, Java treats the number as int — and 7800000000 exceeds int range, causing a compile error.
When in doubt, use int. It handles the vast majority of integer needs and is the fastest type on modern hardware.
Integer overflow
Primitives have fixed sizes. Push past the limit and the value wraps around silently:
int max = Integer.MAX_VALUE; // 2,147,483,647
int overflow = max + 1; // -2,147,483,647 (!!)
System.out.println(overflow);
Java doesn't throw an error — it wraps to the minimum value. This is a common source of bugs. long gives you more room, and BigInteger gives you unlimited precision for when even long isn't enough.
Floating-point numbers
float price = 9.99f; // f suffix needed — default is double
double pi = 3.141592653589793;
Floats approximate decimal numbers. They're not exact:
double result = 0.1 + 0.2;
System.out.println(result); // 0.30000000000000004
This isn't a Java bug — it's how IEEE 754 floating-point works across nearly all languages. For precise decimals (money, banking), use BigDecimal instead.
The char type
char holds a single Unicode character:
char letter = 'A';
char emoji = '😊';
char chinese = '中';
Single quotes for char, double quotes for String. They're different types:
char single = 'A'; // char — one character
String word = "A"; // String — an object with methods
char is actually a numeric type underneath. 'A' is stored as the integer 65:
char letter = 'A';
System.out.println((int) letter); // 65
System.out.println((char) 66); // B
The boolean type
boolean isRunning = true;
boolean hasError = false;
Java booleans can only be true or false — no integers, no truthy/falsy values. This strictness prevents bugs where a number accidentally acts as a boolean condition.
String — not a primitive
String looks primitive but it's a reference type — a class with dozens of built-in methods:
String name = "Ada";
System.out.println(name.length()); // 3
System.out.println(name.toUpperCase()); // ADA
System.out.println(name.charAt(0)); // A
Strings in Java are immutable — once created, they can't be changed. Methods like toUpperCase() return a new String rather than modifying the original.
String original = "hello";
String upper = original.toUpperCase();
System.out.println(original); // hello (unchanged)
System.out.println(upper); // HELLO
Type casting
Converting between types requires explicit action:
// Widening — safe, automatic (smaller to larger)
int myInt = 9;
double myDouble = myInt; // 9.0
// Narrowing — risky, manual (larger to smaller)
double myDouble2 = 9.78;
int myInt2 = (int) myDouble2; // 9 — decimal truncated, not rounded
Widening preserves the value. Narrowing can lose data. The cast operator (int) tells the compiler "I know what I'm doing."
Wrapper classes
Every primitive has a corresponding wrapper class that lives in java.lang:
| Primitive | Wrapper |
|---|---|
int | Integer |
double | Double |
boolean | Boolean |
char | Character |
long | Long |
Wrapper classes are objects — they can hold null, work with generics, and provide utility methods:
int primitive = 42;
Integer wrapped = Integer.valueOf(primitive); // auto-boxing
int unwrapped = wrapped.intValue(); // auto-unboxing
System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Integer.parseInt("123")); // 123
Autoboxing converts primitives to wrappers automatically. Unboxing does the reverse. Java handles this behind the scenes, but understanding it helps when you encounter NullPointerException on a number — it's the wrapper being null.
Mini Practice
- Declare one variable of each primitive type and print its default value
- Calculate
Integer.MAX_VALUE + 1— observe the overflow - Add
0.1 + 0.2withdouble— observe the floating-point imprecision - Convert a
charto its integer value and back - Use
Integer.parseInt()to convert a user-input string to an integer
Next: working with operators →
Related Topics
Frequently Asked Questions about Data Types
What is Data Types in Java?
Data Types is a fundamental concept in Java. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Data Types?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Data Types.
Why is Data Types important in Java?
Data Types is essential for Java development. Understanding this concept will help you write better code and solve real-world problems more effectively.