Java Fundamentals: Types, Control Flow & First Classes
Build a solid Java foundation: primitive and reference types, variables, conditionals and loops, your first classes and objects, and everyday arrays and collections.
4 sections · ~28 min · 5-question quiz (pass ≥ 70%)
1Types, Variables, and the Java Memory Model (Basics)
Java is statically typed: every variable has a declared type checked at compile time. That catches an entire class of bugs before your code ever runs.
Primitive types store values directly: byte, short, int, long, float, double, char, and boolean. Everything else is a reference type — objects live on the heap, and your variable holds a reference (like a pointer) to them.
int count = 42; // primitive — stored inline in the stack frame
String name = "Ada"; // reference — name points at a String object on the heap
final double TAX_RATE = 0.08; // final = cannot reassign the binding
Rules of thumb:
- Use
intfor whole numbers anddoublefor decimals unless you have a specific reason not to. - Prefer
finalfor values that should never change after initialization — it makes intent obvious. Stringliterals are immutable:name.toUpperCase()returns a new String; it does not mutate the original.
2Control Flow: Conditionals, Loops, and switch
Control flow decides which code runs and how often.
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else {
grade = "C";
}
// Enhanced for-loop — preferred for arrays and collections
for (String item : items) {
System.out.println(item);
}
// Classic counter loop when you need the index
for (int i = 0; i < items.length; i++) {
process(items[i], i);
}
switch works on primitives, enums, and (since Java 14+) String. Modern switch expressions can return a value:
String label = switch (status) {
case ACTIVE -> "Running";
case PAUSED -> "On hold";
case STOPPED -> "Stopped";
default -> "Unknown";
};
Avoid == when comparing Strings — use .equals(). == on objects compares references, not content.
3Classes, Objects, and Methods
Java is object-oriented at its core. A class is a blueprint; an object is a live instance created with new.
public class Employee {
private final String name;
private int yearsOfService;
public Employee(String name) {
this.name = name; // constructor runs on new Employee(...)
}
public String getName() {
return name;
}
public void promote() {
yearsOfService++;
}
}
Employee ada = new Employee("Ada");
ada.promote();
Encapsulation means keeping fields private and exposing behavior through public methods. Callers depend on your API, not your internals — you can refactor fields freely later.
Method overloading lets you define multiple methods with the same name but different parameter lists. The compiler picks the right one at compile time based on argument types.
4Arrays and Collections Basics
Arrays are fixed-size, ordered sequences. Great when size is known upfront:
int[] scores = { 95, 87, 72 };
scores[0] = 96; // mutate an element
int len = scores.length; // note: .length, not .length()
String[] names = new String[3]; // all elements start as null
For dynamic sizing, reach for the Collections Framework. ArrayList is the default list implementation:
import java.util.ArrayList;
import java.util.List;
List<String> tasks = new ArrayList<>();
tasks.add("Write tests");
tasks.add("Ship feature");
for (String task : tasks) {
System.out.println(task);
}
Rules of thumb:
- Program to interfaces: declare
List<String>, instantiateArrayList<String>. HashMap<K,V>for key–value lookups;HashSet<T>for unique elements with fast membership checks.- Generics (
List<String>) give compile-time type safety — no casting needed when you read elements back out.