</>
Skip to content
Java lessons (8/47)

Java — Data Types

Two categories of types

Java divides all data into two groups:

  1. Primitive types — simple, built-in values (numbers, characters, booleans)
  2. 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:

TypeSizeRange / Purpose
byte1 byte-128 to 127
short2 bytes-32,768 to 32,767
int4 bytes-2 billion to 2 billion
long8 bytesextremely large integers
float4 bytesdecimal numbers (6–7 digit precision)
double8 bytesdecimal numbers (15 digit precision)
char2 bytessingle Unicode character
boolean1 bittrue 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:

PrimitiveWrapper
intInteger
doubleDouble
booleanBoolean
charCharacter
longLong

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

  1. Declare one variable of each primitive type and print its default value
  2. Calculate Integer.MAX_VALUE + 1 — observe the overflow
  3. Add 0.1 + 0.2 with double — observe the floating-point imprecision
  4. Convert a char to its integer value and back
  5. 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.