Java Data Types Explained: Primitive vs Reference Types, Casting, and Wrapper Classes

目次

1. What Are Java Data Types? Fundamentals and the Big Picture

Java data types are a mechanism that determines what kind of value a variable can store.
Java emphasizes type safety (a design that prevents invalid type operations at compile time), so every variable must have a declared type.

For example, look at the following code.

int number = 10;
double price = 19.8;
String name = "Java";
  • int → integers only
  • double → decimals only
  • String → strings only

By making types explicit, you get benefits like:

  • Prevents invalid assignments
  • Optimizes memory usage
  • Catches bugs at compile time

If there were no types, mistakes like assigning a string to an integer would not be discovered until runtime. Java is designed to prevent that.

1.1 What Is a Data Type? (Beginner-Friendly Definition)

Think of a data type as “the kind of values a variable is allowed to handle.”

The basic syntax is:

TypeName variableName = value;

Example:

int age = 25;

In this case:

  • int is the type
  • age is the variable name
  • 25 is the value

That’s the relationship.

If you write this, you’ll get an error:

int age = "25";  // Compile-time error

You cannot assign a string to an integer type. This is how type safety works.

Common beginner pitfalls

  • Assuming you can omit types (in Java, you generally cannot)
  • Confusing numbers and strings
  • Mixing up = (assignment) and == (comparison)

1.2 Java Data Type Categories (Two Types)

Java data types are broadly divided into two categories:

  1. Primitive types
  2. Reference types

What are primitive types?

Types that store the actual value directly.
Examples: int, double, boolean, etc.

Characteristics:

  • Memory-efficient
  • Fast
  • Cannot hold null

What are reference types?

Types that store not the value itself, but a “reference” to where the value is stored.

Example:

String text = "Hello";

String is a class type (a reference type).

Characteristics:

  • Created based on classes
  • Can be assigned null
  • Has methods (behavior)

1.3 The Difference in “Value vs Reference” Behavior

Let’s confirm the difference with a simple example.

int a = 10;
int b = a;
b = 20;

In this case:

  • a stays 10
  • Only b becomes 20

On the other hand, reference types work like this:

String s1 = "Java";
String s2 = s1;

Here, s1 and s2 may reference the same object (this can vary depending on implementation and optimizations).

Common sticking points

  • Misunderstanding String as a primitive type
  • Assuming copying a reference type copies the value itself
  • Not understanding how null works

1.4 Why Understanding Data Types Matters

Poor understanding of data types can cause problems like:

  • Unexpected calculation results
  • Overflow (exceeding the value range)
  • NullPointerException
  • Type conversion errors

To use Java correctly, you must first understand the overall picture of data types.

2. Primitive Types (Basic Data Types): List and How to Use Them

Primitive types are data types that store the actual value directly.
Java has 8 primitive types.

CategoryTypeSizeTypical Use
Integerbyte8bitSmall integers
Integershort16bitSmaller integers
Integerint32bitStandard integers
Integerlong64bitLarge integers
Decimalfloat32bitSingle-precision floating point
Decimaldouble64bitDouble-precision floating point (standard)
Characterchar16bitA single character
Booleanbooleantrue / false

*Sizes are fixed by the Java specification (not environment-dependent).

2.1 Integer Types (byte / short / int / long)

Basic usage

int number = 100;
long population = 8000000000L;

Ranges (common examples)

  • byte: -128 to 127
  • short: -32,768 to 32,767
  • int: approx. ±2.1 billion
  • long: approx. ±9.22 quintillion

In most cases, int is enough.
There’s rarely a practical need to use byte or short just to save memory.

Important note when using long

long value = 10000000000L;  // L is required

Without the L, the literal is treated as an int and can cause a compile-time error due to out-of-range.

Common mistakes

  • Overflowing by exceeding the range
  • Forgetting L for long literals
  • Not noticing overflow in int-to-int calculations

2.2 Floating-Point Types (float / double)

double price = 19.99;
float rate = 0.5f;

Basic rules

  • Typically, use double
  • float requires a trailing f
float value = 3.14f;

Precision differences

  • float: about 7 digits of precision
  • double: about 15 digits of precision

Important note (rounding/precision issues)

System.out.println(0.1 + 0.2);

The result may not be exactly 0.3.
This is due to binary floating-point representation.

Money calculations

For money handling, double is generally not recommended.
Using BigDecimal is safer.

Common mistakes

  • Using double for money
  • Confusing float and double
  • Comparing decimals with ==

2.3 Character Type (char)

char letter = 'A';
  • Uses single quotes
  • Managed with Unicode (a character encoding standard)
  • Can store only one character
char kanji = '日';

Common mistakes

  • Using double quotes (that is String)
  • Trying to store multiple characters

2.4 Boolean Type (boolean)

boolean isActive = true;
  • Values are only true or false
  • You cannot use 0/1 (unlike C)
boolean result = (5 > 3);

Common mistakes

  • Trying to assign a number
  • Forgetting to write the comparison expression

2.5 Common Notes for Primitive Types

  • You cannot assign null
  • Default values are automatically set for fields, but local variables must be initialized
int x;
System.out.println(x);  // Compile-time error (uninitialized)

Primitive types are fast and lightweight, but they have limitations such as not supporting null and not having methods.

3. Reference Types: The Basics

Reference types store not the value itself, but a reference (memory address) to an object.
The biggest difference from primitive types is that the “data itself” and the “variable” exist separately.

Look at this example:

String text = "Java";

Here, text stores a reference to the string object, not the string value itself.

3.1 String Type (The Most Commonly Used Reference Type)

String is a class type. It is not a primitive type.

String name = "Taro";

Characteristics

  • Immutable (cannot be changed)
  • Can be assigned null
  • Has methods
String str = "Hello";
System.out.println(str.length());  // 5

Immutability gotcha

String s = "Java";
s.concat(" SE");
System.out.println(s);  // "Java"

concat() returns a new string, but the original string is not modified.

Correct usage:

s = s.concat(" SE");

Common mistakes

  • Assuming String is a primitive type
  • Using == for string comparison
  • Heavy concatenation causing performance issues (use StringBuilder)

3.2 Arrays and Class Types

Arrays

int[] numbers = {1, 2, 3};

Arrays are also reference types.

int[] a = {1, 2};
int[] b = a;
b[0] = 99;

System.out.println(a[0]);  // 99

Since a and b reference the same array, changes affect both.

Class types

class Person {
    String name;
}

Person p = new Person();
p.name = "Ken";

new is the keyword used to create an object.

3.3 What Is null?

null represents a state where “there is no referenced object.”

String text = null;

Calling a method when a reference is null causes an error.

text.length();  // NullPointerException

This is called a NullPointerException (NPE).

How to handle null

if (text != null) {
    System.out.println(text.length());
}

3.4 The Difference Between == and equals()

== (reference comparison)

Compares whether the memory addresses are the same.

equals() (content comparison)

Compares whether the contents are the same.

String a = new String("Java");
String b = new String("Java");

System.out.println(a == b);        // false
System.out.println(a.equals(b));   // true

Common mistakes

  • Using == for string comparison
  • Calling equals() without checking for null
  • Mixing up copying references and copying values

3.5 Quick Summary: Differences from Primitive Types

ItemPrimitive TypesReference Types
StoresThe value itselfA reference
nullNot allowedAllowed
MethodsNoYes
newNot neededUsually needed

Reference types are flexible, but you must be careful about null handling and shared references.

4. Wrapper Classes and Autoboxing

Wrapper classes are classes that let you treat primitive values as objects.
In Java, collections (like List and Map) can only store reference types, so you cannot store primitives directly. Wrapper classes exist for that purpose.

4.1 Common Wrapper Classes

Primitive TypeWrapper Class
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

Example:

Integer number = 10;
Double price = 19.99;

Since wrapper classes are reference types, they can hold null.

Integer value = null;  // OK

4.2 What Is Autoboxing?

Boxing means converting a primitive type into a wrapper class.

Since Java 5, this conversion can happen automatically.

Integer num = 10;  // autoboxing

Internally, this is equivalent to:

Integer num = Integer.valueOf(10);

4.3 What Is Unboxing?

Unboxing converts a wrapper class back into a primitive type.

Integer num = 20;
int value = num;  // auto-unboxing

Internally:

int value = num.intValue();

4.4 When You Need Wrapper Classes

1. When using collections

import java.util.ArrayList;

ArrayList<Integer> list = new ArrayList<>();
list.add(10);  // autoboxing

You cannot use ArrayList<int>.

2. When you need to handle null

Integer score = null;

Primitive types cannot be null.

4.5 Notes and Common Mistakes

1. Exception when unboxing null

Integer num = null;
int value = num;  // NullPointerException

An exception occurs during auto-unboxing.

2. Comparing with ==

Integer a = 1000;
Integer b = 1000;

System.out.println(a == b);  // may be false

Because these are objects, == compares references.
Use equals() for content comparison.

a.equals(b);

3. Performance impact

Wrapper classes can involve object creation,
so heavy computations may be slower than using primitive types.

4.6 Choosing Between Primitive Types and Wrapper Classes

  • Numeric calculations → primitive types
  • Storing in collections → wrapper classes
  • Handling null → wrapper classes

If you remember these guidelines, you won’t hesitate in real-world work.

5. Type Conversion (Casting): The Basics

In Java, when you work with values across different data types, you use type conversion (casting).
There are two main kinds:

  • Implicit conversion (widening conversion)
  • Explicit conversion (narrowing conversion)

5.1 Implicit Conversion (Widening)

Conversions from a smaller-range type to a larger-range type happen automatically.

int num = 100;
long bigNum = num;  // automatic conversion

This is safe because it expands the numeric range.

Conversion order (integer-related example)

byte → short → int → long → float → double

Example

int a = 10;
double b = a;  // OK

Notes

  • Precision is preserved in many cases, but rounding can occur with float or double.
  • char can be converted as an integer value.
char c = 'A';
int code = c;  // 65

5.2 Explicit Conversion (Narrowing)

When converting from a larger type to a smaller type, you must cast explicitly.

double price = 19.99;
int rounded = (int) price;

The result is:

rounded = 19

The fractional part is truncated.

Syntax

(TargetType) variable

5.3 Example of Data Loss

int big = 1000;
byte small = (byte) big;
System.out.println(small);

The result is not “unpredictable,” but rather wrapped to fit within the target range.
Here, 1000 exceeds the byte range, so the value changes.

Common misconceptions

  • Thinking it will cause an error → in reality, the value changes
  • Assuming it’s always safe → data loss can occur

5.4 A Pitfall: Integer Division

int a = 5;
int b = 2;
double result = a / b;
System.out.println(result);

The result is:

2.0

Integer division is performed as an integer operation.

Correct approach:

double result = (double) a / b;

Result:

2.5

5.5 Notes on Comparing Decimals

double x = 0.1 + 0.2;
System.out.println(x == 0.3);  // may be false

This is due to floating-point precision issues.

A safer comparison

Math.abs(x - 0.3) < 0.000001

5.6 Casting Reference Types

You can also cast reference types (when there is an inheritance relationship).

Object obj = "Java";
String str = (String) obj;

Casting to an incorrect type causes an exception.

Integer num = (Integer) obj;  // ClassCastException

Common Mistakes Summary

  • Out-of-range conversions change values
  • Not noticing integer division
  • Comparing decimals with ==
  • Forcing invalid reference casts

Casting often does not trigger compile-time errors, so misunderstandings can easily lead to bugs.

6. A Practical Type Selection Guide (So You Don’t Hesitate at Work)

Now that you understand how Java data types work, a common real-world question is: “Which type should I use?” This section organizes practical decision criteria.

6.1 Why int and double Are Usually Enough

Use int for integers (by default)

int count = 100;

Reasons:

  • 32-bit range is sufficient for most cases
  • Easier for the JVM to optimize
  • Readable and standard

You typically don’t need to force byte or short usage.
Choosing smaller types just to save memory is usually only for special cases (like huge arrays).

Use double for decimals (by default)

double rate = 0.75;

It has higher precision than float and is the standard choice.
Unless you have a clear reason, choose double.

6.2 Why You Should Use BigDecimal for Money

This code is risky for money:

double price = 0.1 + 0.2;

Because of floating-point errors, you may not get an exact value.

Correct approach:

import java.math.BigDecimal;

BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal result = a.add(b);

Why pass strings?

new BigDecimal(0.1);  // not recommended

Creating from a double can carry over its precision error.

Common mistakes

  • Handling money with double
  • Using new BigDecimal(doubleValue)
  • Forgetting rounding rules

6.3 Collections Require Wrapper Classes

import java.util.ArrayList;

ArrayList<Integer> list = new ArrayList<>();
list.add(10);

You cannot use primitive types directly.

ArrayList<int> list;  // Compile-time error

Reason:

  • Generics (type-safe collections) support reference types only

6.4 Decide Based on Whether You Need null

No null needed → primitive types

int age = 0;

null needed → wrapper classes

Integer age = null;

In database integrations or form inputs, you may need null handling.

6.5 Basic Performance Guidelines

  • Calculations → primitive types
  • Collections → wrapper classes
  • Avoid creating wrappers inside tight loops

Example (not recommended):

for (Integer i = 0; i < 1000000; i++) { }

Using primitive types is more efficient.

6.6 Summary Table: Recommended Types by Use Case

Use CaseRecommended Type
Typical integersint
Typical decimalsdouble
MoneyBigDecimal
Boolean checksboolean
StringsString
Storing in collectionsWrapper classes

Common Real-World Mistakes

  • Choosing unnecessarily small types
  • Using double for money
  • Designing without considering null
  • Auto-unboxing exceptions from wrapper classes

Type selection is a core part of design. If you proceed with ambiguity, the cost of fixing issues later increases significantly.

7. Java Data Types Summary (With Tables)

Let’s summarize everything in a format that answers common search intent quickly.
Java data types are divided into “primitive types” and “reference types.”

7.1 Primitive Types List

TypeSizeDefault (fields)Typical Use
byte8bit0Small integers
short16bit0Smaller integers
int32bit0Standard integers
long64bit0LLarge integers
float32bit0.0fSingle-precision floating point
double64bit0.0dStandard floating point
char16bit‘\u0000’A single character
booleanfalseBoolean value

*Local variables are not automatically initialized.

Key points

  • For numeric calculations, default to int / double
  • For money, use BigDecimal
  • null is not allowed
  • No methods

7.2 Reference Types Overview

Typical reference types:

  • String
  • Arrays (e.g., int[])
  • Class types (custom classes)
  • Wrapper classes (e.g., Integer)
  • Collections (List, Map, etc.)

Summary of characteristics

ItemReference Types
Can assign nullYes
MethodsAvailable
new keywordUsually needed
Comparisonequals() recommended

7.3 Final Comparison: Primitive vs Reference

PerspectivePrimitive TypesReference Types
StoresDirectlyBy reference
Memory efficiencyHighSomewhat lower
nullNoYes
SpeedFastSomewhat slower
Main useCalculationsObject handling

7.4 The Minimal Set Beginners Should Learn First

Start with these four types:

  • int
  • double
  • String
  • boolean

With these, you can build basic programs.

7.5 Common Overall Mistakes

  1. Comparing String with ==
  2. Using double for money
  3. Not noticing integer division
  4. Forgetting null checks
  5. Forgetting L for long literals
  6. Unboxing null in wrapper classes

Avoiding these alone will significantly reduce beginner errors.

7.6 Final Takeaways

  • Java is a type-safe language
  • Understanding data types is the foundation of all code
  • Primitive types are for fast calculations
  • Reference types are for managing objects
  • Choosing the right type directly affects quality

FAQ

Q1. How many Java data types are there?

Answer:
There are 8 primitive types. Reference types can be countless (classes, arrays, interfaces, etc.). It’s important to first understand the 8 primitive types.

Q2. Is String a primitive type?

Answer:
No. String is a class type (a reference type). It is treated as an object and can be assigned null.

Q3. What’s the difference between int and Integer?

Answer:
int is a primitive type. Integer is a wrapper class (a reference type). Integer can hold null, but auto-unboxing may throw an exception.

Q4. Can I use double for money calculations?

Answer:
Technically yes, but it’s not recommended. Floating-point precision issues can occur, so using BigDecimal is safer.

Q5. Why doesn’t dividing integers produce a decimal?

Answer:
Because integer operations are performed using integer types, the fractional part is truncated. If you need a decimal result, cast one operand to double.

Q6. What is null?

Answer:
It represents a state where no object is referenced. Calling a method on null causes a NullPointerException.

Q7. What’s the difference between == and equals()?

Answer:
== compares references (memory addresses). equals() compares contents. For string comparison, use equals().

Q8. Which types should beginners learn first?

Answer:
Prioritize int, double, String, and boolean. These are the most commonly used core types in real work.