🧮 [4] Data Types & Variables — The Core Foundation of Java!
✨ Introduction
Data types are the DNA of Java. Every variable you use — whether a number, letter, sentence, or boolean — has a type. Java is a statically-typed language, meaning every variable must have a type defined at compile time.
This post will teach you everything from simple int values to complex memory behavior behind the scenes. If you're ready to go from beginner to confident coder, let's dive deep.
🔢 Java Data Types Overview
🧱 Primitive Types (8 total)
Java has 8 built-in (primitive) data types:
| Type | Size | Default | Max Value | Example |
|---|---|---|---|---|
byte |
1 byte | 0 | 127 | byte b = 100; |
short |
2 bytes | 0 | 32,767 | short s = 10000; |
int |
4 bytes | 0 | 2,147,483,647 | int x = 42; |
long |
8 bytes | 0L | 9,223,372,036,854,775,807 | long l = 123456789L; |
float |
4 bytes | 0.0f | ~3.4e+38 | float pi = 3.14f; |
double |
8 bytes | 0.0 | ~1.7e+308 | double d = 9.81; |
char |
2 bytes | '\u0000' |
65,535 (unsigned) | char c = 'A'; |
boolean |
1 bit (logical) | false | true / false only | boolean isOn = true; |
🧪 Example:
byte a = 127;
short b = 32000;
int c = 100000;
long d = 123456789L;
float e = 5.75f;
double f = 19.99;
char grade = 'A';
boolean isJavaFun = true;
🧠 Reference Data Types
These include String, arrays, classes, interfaces, etc. They store the memory address of the object, not the actual value.
Example:
String name = "Java Learner";
int[] numbers = {1, 2, 3, 4};
📦 Variable Declaration
Syntax: type variableName = value;
🧪 Example:
int age = 25;
double height = 5.9;
String language = "Java";
🔍 Primitive vs Reference Types in Java
| Feature | Primitive Type | Reference Type |
|---|---|---|
| Definition | Basic data types that store actual values | Objects that store references (addresses) to memory locations |
| Stored Value | The actual data (like number, character) | A reference (or pointer) to the actual object in heap memory |
| Examples | int, float, boolean, char, byte, short, long, double |
String, Arrays, Classes, Scanner, List, etc. |
| Memory Location | Stored on the stack | Reference is on stack, actual object is on the heap |
| Default Value | Depends on type (e.g., int = 0, boolean = false) |
null |
| Mutability | Immutable — you create new values when changing | Objects can be mutable or immutable depending on class |
| Operations | Basic arithmetic and logical operations directly apply | Use methods or functions (e.g., str.length()) |
| Comparison | Compared using == (value comparison) |
Use .equals() for content; == compares reference |
| Wrapper Classes | Yes — int → Integer, double → Double |
Already objects — no need for wrappers |
| Garbage Collection | Not applicable — primitive variables are automatically cleaned | Yes — handled by Java Garbage Collector for unused objects |
💡 Summary
Use primitive types for efficiency and simple value storage (like numbers, booleans).
Use reference types when working with objects, data structures, and more complex data.
🧠 Memory in Java — Stack vs Heap
Java uses a managed memory model with two primary regions:
✅ 1. Stack Memory
| 🔹 Feature | 🔹 Description |
|---|---|
| 📦 Stores | Method calls, local variables, references |
| 🧠 Location | Each thread has its own stack |
| ⚡ Fast? | Very fast — grows/shrinks with method calls |
| 🔐 Access | Automatically managed — pops off when method ends |
Example:
public class MemoryDemo {
public static void main(String[] args) {
int x = 10; // x lives in the stack
String name = "Java"; // reference in stack, object in heap
}
}
- 🧠
xis stored directly in the stack - 📍
nameis a reference in the stack, pointing to the string"Java"in the heap
✅ 2. Heap Memory
| 🔹 Feature | 🔹 Description |
|---|---|
| 📦 Stores | All objects and class instances |
| 🧠 Shared? | Yes, shared across all threads |
| ♻️ GC Managed | Yes — cleaned by Garbage Collector |
| 🐢 Speed | Slower access than stack |
Example:
class Person {
String name;
}
public class HeapExample {
public static void main(String[] args) {
Person p1 = new Person(); // p1 → reference in stack
p1.name = "Aelify"; // Object stored in heap
System.out.println("Person's name is: " + p1.name);
}
}
/*
+---------------------+
| Stack Memory |
+---------------------+
| p1 (ref to Person) | -----------+
+---------------------+ |
v
+-----------------------------+
| Heap Memory |
+-----------------------------+
| Person object |
| +-----------------------+ |
| | name --> "Aelify" | |
| +-----------------------+ |
+-----------------------------+
Notes:
- p1 is a local variable stored on the stack.
- The Person object is created on the heap.
- The 'name' field inside Person is a reference to another object ("Aelify") also in the heap.
*/
✅ Output:
Person's name is: Aelify
p1is in the stacknew Person()object is in the heap
✅ Explanation: In Java, local variables like p1 are stored in the stack, but the actual Person object is created in the heap. The variable p1 holds the reference to the heap memory.
❌ Expected Mistake: Beginners often think the entire object is in the stack — but only the reference is!
⚠️ Common Mistakes
- ❌ Thinking all variables are stored in the same place
- ❌ Misunderstanding how references work (e.g., copying references just copies the address, not the object)
- ❌ Forgetting about Garbage Collection — heap objects are auto-deleted if unused
🔄 Type Casting in Java
👉 Implicit Casting (Widening)
Smaller type to larger type — safe.
int x = 10;
double y = x; // implicit cast int → double
👉 Explicit Casting (Narrowing)
Larger type to smaller — risky if out of bounds.
double pi = 3.14159;
int approx = (int) pi; // 3
📉 Overflow & Underflow
Java does not throw an error if integers overflow — they wrap around.
int max = Integer.MAX_VALUE;
System.out.println(max + 1); // Output: -2147483648
🔹 What is Type Casting?
Type casting means converting one data type into another. In Java, there are two kinds:
✅ 1. Implicit Casting (Widening Conversion)
- ✔️ Done automatically by Java
- ✔️ Happens when converting smaller → larger types
| From | To |
|---|---|
| byte | short, int, long, float, double |
| int | long, float, double |
int x = 100;
double y = x; // Implicit casting
System.out.println(y); // 100.0
✅ Explanation: Java automatically converts int to double without loss.
❌ Expected Mistake: Thinking it will behave differently or cause rounding — it won’t.
✅ 2. Explicit Casting (Narrowing Conversion)
- ❌ Not automatic
- ❌ You must use manual cast syntax
double value = 5.99;
int result = (int) value;
System.out.println(result); // 5
✅ Explanation: Truncates the decimal, does NOT round
❌ Expected Mistakes:
- Forgetting parentheses:
int result = value;→ Compile error - Expecting 6 as output due to rounding
✅ Overflow Example:
int big = 130;
byte b = (byte) big;
System.out.println(b); // Output: -126
✅ Explanation: byte max = 127
130 causes overflow:
130 - 256 = -126 due to 2’s complement wrapping.
✅ Overflow Example (Beginner-Friendly Explanation 😄)
int big = 130;
byte b = (byte) big;
System.out.println("After casting: " + b); // Output: After casting: -126
✅ Explanation: Java uses 2's complement binary format to store negative numbers in byte-sized containers.
byteholds values between -128 and 127.130is too big for abyte, so Java wraps it around.- It subtracts
256(the total number of values in a byte) from130to get-126.
🔍 How It Works (Visually)
- Imagine a circle with numbers from
-128to127. - If you move past
127, you loop back to the negative side. - Example overflow steps:
128 → -128129 → -127130 → -126
// Manual Wrap Around Logic
int wrapped = 130 - 256; // byte can hold 256 values total
System.out.println(wrapped); // Output: -126
🔢 What Is 2's Complement?
- It’s how computers store negative numbers in binary.
- The leftmost bit (most significant bit) indicates the sign:
0→ positive1→ negative
- When overflow happens, the binary rolls over like a digital counter, flipping bits.
⚠️ Expected Mistake: Many assume Java will throw an error or round the number — it doesn’t. It silently wraps.
✅ Important: Always check value ranges before casting to smaller types like byte or short.
🧠 Mini Practice
float f = 7.5f;
int x = (int) f;
System.out.println(x);
✅ Output: 7
❌ Mistake: Assuming it will round to 8
🔬 Summary Table: Type Casting
| Casting Type | Automatic? | Direction | Risk of Data Loss? | Syntax |
|---|---|---|---|---|
| Implicit (Widening) | ✅ Yes | Smaller → Larger | ❌ No | double d = intVal; |
| Explicit (Narrowing) | ❌ No | Larger → Smaller | ✅ Yes | int i = (int) 5.9; |
🔄 Type Casting Examples in Java
Java allows converting between data types using type casting. It happens in two ways:
- Implicit Casting (Widening) — ✅ safe, automatic
- Explicit Casting (Narrowing) — ❌ risky, manual
✅ Implicit Casting Examples (Automatic)
// byte → int
byte b = 10;
int num = b;
System.out.println(num); // 10
// int → double
int marks = 85;
double result = marks;
System.out.println(result); // 85.0
// char → int
char ch = 'A';
int ascii = ch;
System.out.println(ascii); // 65
⚠️ Common Mistake: Expecting int → float to lose precision. It doesn’t!
❌ Explicit Casting Examples (Manual)
// double → int (Truncates decimals)
double d = 7.99;
int x = (int) d;
System.out.println(x); // 7
// int → byte (Risk of overflow!)
int big = 130;
byte small = (byte) big;
System.out.println(small); // -126
// long → short
long population = 30000L;
short popShort = (short) population;
System.out.println(popShort); // 30000 (✅ fits safely)
// float → int
float pi = 3.14f;
int intPi = (int) pi;
System.out.println(intPi); // 3
// char → byte
char c = 'B'; // 66
byte bc = (byte) c;
System.out.println(bc); // 66
⚠️ Expected Mistakes:
- Forgetting parentheses:
int x = d;❌ Error - Thinking casting rounds instead of truncates:
7.99 → 8 ❌ - Not checking overflow when casting large numbers
🧪 Practice + Answers
🔹 Q1. Cast a float to int
float f = 9.8f;
int i = (int) f;
System.out.println(i); // Output: 9
🔹 Q2. Implicit cast char → int
char c = 'Z';
int ascii = c;
System.out.println(ascii); // Output: 90
🔹 Q3. Overflow example: int → byte
int num = 258;
byte b = (byte) num;
System.out.println(b); // Output: 2
✅ Because 258 - 256 = 2 (wrapped around)
🔹 Q4. What happens when you cast double to int?
double val = 6.9999;
int n = (int) val;
System.out.println(n); // Output: 6
🔹 Q5. Combine implicit and explicit casts
byte a = 50;
int x = a; // implicit
float f = x; // implicit
int back = (int) f; // explicit
System.out.println(back); // Output: 50
📌 Summary Table — Casting Overview
| From | To | Type | Syntax | Risk |
|---|---|---|---|---|
| int | double | Implicit | double d = i; | No |
| double | int | Explicit | int i = (int) d; | Yes |
| char | int | Implicit | int i = c; | No |
| int | byte | Explicit | byte b = (byte) i; | Yes |
✅ Reminder: Use explicit casting carefully — always check the range of your destination type!
💥 Overflow in Java — All Primitive Types (Full Explanation)
In Java, overflow happens when a value goes beyond the range of a primitive type. For integer types, Java silently wraps the value using 2's complement logic. For floating-point types, it becomes Infinity.
1️⃣ byte Overflow
byte b = (byte) 130;
System.out.println(b); // Output: -126
✅ Explanation:
byterange is -128 to 127 (8-bit signed)- 130 - 256 = -126 → wraps around using 2's complement
- Beginners expect an error or rounding — Java wraps it silently
2️⃣ short Overflow
short s = (short) 40000;
System.out.println(s); // Output: -25536
✅ Explanation:
shortrange is -32,768 to 32,767 (16-bit signed)- 40000 - 65536 = -25536 (65536 = 216)
- People assume short can handle any 5-digit number — not always true
3️⃣ int Overflow
int x = Integer.MAX_VALUE; // 2,147,483,647
x = x + 1;
System.out.println(x); // Output: -2147483648
✅ Explanation:
intrange is -231 to 231-1- Adding 1 to max value wraps around to the negative side
- Assuming Java throws an error — it just wraps around
4️⃣ long Overflow
long l = Long.MAX_VALUE; // 9,223,372,036,854,775,807
l = l + 1;
System.out.println(l); // Output: -9223372036854775808
✅ Explanation:
longrange is -263 to 263-1- It wraps to minimum value after overflow
- Assuming large numbers like this are safe — overflow still happens
5️⃣ char Overflow
char c = 65535; // max char value
c++;
System.out.println((int) c); // Output: 0
✅ Explanation:
charis an unsigned 16-bit type → range 0 to 65535- Adding 1 wraps it back to 0
- People confuse
charwith signed numbers — it’s always positive
6️⃣ float Overflow
float f = Float.MAX_VALUE;
f = f * 100;
System.out.println(f); // Output: Infinity
✅ Explanation:
floatmax value is approx 3.4 × 1038- When exceeded, it turns into
Infinity
- People expect float to wrap or clamp — but it just becomes
Infinity
7️⃣ double Overflow
double d = Double.MAX_VALUE;
d = d * 2;
System.out.println(d); // Output: Infinity
✅ Explanation:
doublemax value is approx 1.8 × 10308- Exceeding it results in
Infinity
- Expecting it to crash — Java just prints
Infinity
8️⃣ boolean (No Overflow)
boolean b = true;
b = !b;
System.out.println(b); // Output: false
✅ Explanation:
booleanonly storestrueorfalse- It cannot overflow — any attempt to assign numbers gives a compile-time error
- Trying to assign integers like
1or0→ Java won't allow it
📘 Summary Table
| Type | Min | Max | Overflow Result |
|---|---|---|---|
| byte | -128 | 127 | Wraps to -128 → up |
| short | -32,768 | 32,767 | Wraps to -32,768 → up |
| int | -231 | 231 - 1 | Wraps to negative |
| long | -263 | 263 - 1 | Wraps to negative |
| char | 0 | 65,535 | Wraps to 0 |
| float | ~ -3.4×1038 | ~ 3.4×1038 | Infinity |
| double | ~ -1.8×10308 | ~ 1.8×10308 | Infinity |
| boolean | false | true | No overflow |
🎯 Final Tip
✅ Always check ranges using constants like Byte.MAX_VALUE, Integer.MIN_VALUE, etc., before performing casts or calculations to prevent unexpected overflows.
📌 Final Keyword (Constants)
Use final in Java to create constants — values that cannot be changed after initialization.
final double GRAVITY = 9.8;
✅ Explanation: The keyword final locks the variable. Once you assign a value, you can’t change it later. Trying to do so will cause a compile-time error.
🧪 Example 1: Basic Constant
Q: Can I change the value of a final variable after assigning it?
final int SPEED_LIMIT = 60;
System.out.println("Speed limit: " + SPEED_LIMIT);
SPEED_LIMIT = 80; // ❌ Error: cannot assign a value to final variable
✅ Explanation: Once SPEED_LIMIT is set to 60, it’s locked. The reassignment to 80 is illegal.
❌ Expected Mistake: Trying to reassign a final variable.
🧪 Example 2: Final with Objects
Q: Can I change the internal state of a final object?
final StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Output: Hello World
✅ Explanation: You can't reassign sb to a new object, but you can modify its content.
❌ Expected Mistake: Thinking final makes objects fully unchangeable. It only protects the reference, not the object itself.
🧪 Example 3: Final Parameters
Q: What happens if I declare a method parameter as final?
public class FinalParameterExample {
public static void main(String[] args) {
greet("Aelify");
}
static void greet(final String name) {
// name = "GitHub"; // ❌ Error: cannot assign a value to final parameter
System.out.println("Hello, " + name);
}
}
✅ Explanation: The name parameter is marked as final, which means it cannot be reassigned within the method. This is useful for protecting input arguments from accidental changes.
❌ Expected Mistake: Trying to reassign the parameter (e.g. name = "GitHub";) will result in a compile-time error.
🧪 Example 4: Final with Loops
Q: Can I use final in a loop variable?
for (final int i = 0; i < 3; i++) {
System.out.println(i); // ❌ Error: cannot assign a value to final variable
}
✅ Explanation: Since loop counters are modified on each iteration, they can’t be final. This will throw a compile-time error.
❌ Expected Mistake: Using final for variables that must change in a loop.
📌 Summary of final
- ✅ Use
finalto make variables constant. - 🛡️ Final variables can be initialized once — no reassignment allowed.
- 🧠 With objects,
finallocks the reference, not the object's content. - 📦 Useful for constants like
PI,GRAVITY, etc.
🧠 Exercises — Practice Time!
💡 Beginner
- Declare variables for name, age, and GPA. Print them.
- Cast a
doublevalue (7.9) toint. What do you get? - Store your favorite character in a
char.
🧪 Intermediate
- Write a program that takes an
intinput and shows if it's within thebyterange (-128 to 127). - Demonstrate implicit casting by assigning
inttodouble. - Create two variables:
String firstNameandlastName— print the full name.
🔥 Challenge
- Create a program to calculate the area of a circle given radius. Use
final double PI = 3.14159. - Write a program that causes overflow in an
intand prints the result.
⚠️ Common Mistakes
- ❌ Using
intinstead ofdoublefor decimal values. - ❌ Forgetting 'f' in
floatliterals — e.g.,float x = 3.14f; - ❌ Mixing
charandString—'A'vs"A" - ❌ Overflowing
byteorshortaccidentally. - ❌ Trying to modify
finalvariables — it’s not allowed. - ❌ Expecting compiler to warn about overflow — it won’t.
- ❌ Using undeclared variables
- ❌ Declaring variables inside condition or loop, then trying to use them outside
✅ Recap
- Primitive vs Reference data types
- Memory size and default values
- Type casting (safe vs risky)
- Overflow and memory behavior
- Constants with
final
🧠 Answers — Practice Time (with Explanations)
💡 Beginner
-
Declare variables for name, age, and GPA. Print them.
✅ Explanation: Basic variable declaration uses appropriate data types:String name = "Aelify"; int age = 20; double gpa = 3.8; System.out.println("Name: " + name); System.out.println("Age: " + age); System.out.println("GPA: " + gpa);String,int, anddouble.
❌ Expected Mistakes:- Using
floatorintfor GPA, which may lose precision. - Missing
;at the end of statements. - Misspelling
System.out.println.
- Using
-
Cast a
doublevalue (7.9) toint. What do you get?
✅ Explanation: Casting adouble value = 7.9; int result = (int) value; System.out.println("Casted value: " + result); // Output: 7doubletointtruncates the decimal (no rounding).
❌ Expected Mistake: Assuming the result will be 8 due to rounding. -
Store your favorite character in a
char.
✅ Explanation:char letter = 'J'; System.out.println("Favorite character: " + letter);charstores a single character surrounded by single quotes.
❌ Expected Mistakes:- Using double quotes (
"J") — which is aString, not achar. - Trying to store multiple characters like
'Java'in achar.
- Using double quotes (
🧪 Intermediate
-
Check if input
intis withinbyterange:
✅ Explanation: Aimport java.util.Scanner; public class ByteCheck { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Enter an integer: "); int num = sc.nextInt(); if (num >= -128 && num <= 127) { System.out.println("This number fits in a byte."); } else { System.out.println("This number does NOT fit in a byte."); } sc.close(); } }bytecan hold values from -128 to 127. This checks that range.
❌ Expected Mistakes:- Using incorrect operators like
=<instead of<=. - Forgetting to import
java.util.Scanner.
- Using incorrect operators like
-
Implicit casting from
inttodouble:
✅ Explanation: Java automatically casts smaller types (int a = 42; double b = a; System.out.println("Double value: " + b);int) to larger types (double) without explicit syntax.
❌ Expected Mistake: Trying to manually cast when not needed or thinking it's an error. -
Print full name using two
Stringvariables:
✅ Explanation: UseString firstName = "Aelify"; String lastName = "GitHub"; System.out.println("Full Name: " + firstName + " " + lastName);+for string concatenation, and don’t forget the space between names.
❌ Expected Mistake: Omitting the space, resulting in output likeAelifyGitHub.
🔥 Challenge
-
Calculate area of a circle using
final double PI:import java.util.Scanner; public class CircleArea { public static void main(String[] args) { final double PI = 3.14159; Scanner sc = new Scanner(System.in); System.out.print("Enter radius: "); double radius = sc.nextDouble(); double area = PI * radius * radius; System.out.println("Area of circle: " + area); sc.close(); } }import java.util.Scanner; public class CircleAreaUsingMathPow { public static void main(String[] args) { final double PI = 3.14159; Scanner sc = new Scanner(System.in); System.out.print("Enter radius: "); double radius = sc.nextDouble(); double area = PI * Math.pow(radius, 2); System.out.println("Area of circle: " + area); sc.close(); } }
✅ Explanation:import java.util.Scanner; public class CircleAreaRounded { public static void main(String[] args) { final double PI = 3.14159; Scanner sc = new Scanner(System.in); System.out.print("Enter radius: "); double radius = sc.nextDouble(); double area = PI * radius * radius; // Round to 2 decimal places String roundedArea = String.format("%.2f", area); System.out.println("Area of circle: " + roundedArea); sc.close(); } }finalmakes PI a constant, andradius * radiusis squaring.
❌ Expected Mistakes:- Using
Math.pow(radius, 2)incorrectly or unnecessarily for simple squaring. - Forgetting to declare PI or not marking it as
final.
- Using
-
Cause overflow in
intand print result:
✅ Explanation: Java doesn't raise an error for overflow — it wraps to the negative range.int max = Integer.MAX_VALUE; System.out.println("Before Overflow: " + max); // Before Overflow: 2147483647 System.out.println("After Overflow: " + (max + 1)); // After Overflow: -2147483648
❌ Expected Mistake: Thinking Java will stop or throw an exception — it won't!
You’ve now mastered how Java handles data at the core level. This is the foundation for everything to come, especially logic-heavy tasks, conditions, OOP, and collections.
In our next post, we'll dive into 🔧 [5] Operators & Control Flow — Decision Making in Java!
— Blog by Aelify (ML2AI.com)