Interactive � 3D � 41 lessons

Learn Java by watching it run.

From Hello World to virtual threads and the JVM memory model — every concept comes with a 3D visualization you can rotate.

1 � Foundations � lesson 1 of 41

What is Java & the JVM?

Write once, run anywhere — how bytecode and the JVM make it possible.

Java is a statically typed, object-oriented language that compiles to platform-neutral bytecode. The Java Virtual Machine (JVM) loads that bytecode and executes it on any operating system.

The lifecycle: your .java source is compiled by javac into a .class file of bytecode. The JVM's class loader pulls those classes into memory, the bytecode verifier checks them, and the execution engine (interpreter + JIT compiler) runs them — turning hot code paths into optimized native machine code at runtime.

The pipeline in one line
Hello.java  \u2192  javac  \u2192  Hello.class  \u2192  JVM  \u2192  native CPU
TIPRotate the 3D JVM below to see the ClassLoader, Runtime Data Areas and Execution Engine as separate stages that data flows through.
3D � jvm
KEY TAKEAWAYS
  • \u2713 Java source compiles to bytecode, not to a specific CPU.
  • \u2713 The JVM is the portable runtime; different JVMs exist for different OSes.
  • \u2713 The JIT compiler turns hot methods into fast native code while the program runs.
1 � Foundations � lesson 2 of 41

Hello, World

Your first program — and every piece of the required ceremony explained.

Every Java program starts inside a class, and execution begins at a method named main with a very specific signature.

Java
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
  • \u25b8public — visible to the JVM launcher outside this class.
  • \u25b8class Hello — the container; filename must be Hello.java.
  • \u25b8static — no instance is needed to call main.
  • \u25b8void — main returns nothing.
  • \u25b8String[] args — command-line arguments.
NOTESystem.out is a PrintStream; println writes a line to standard output.
KEY TAKEAWAYS
  • \u2713 Filename must match the public class name.
  • \u2713 main has a fixed signature: public static void main(String[]).
  • \u2713 Statements end with a semicolon; blocks use braces.
1 � Foundations � lesson 3 of 41

Variables & Primitive Types

Eight primitive types, one reference world, and why the difference matters.

Java has 8 primitive types stored directly on the call stack, and reference types whose values live on the heap while a reference to them sits on the stack.

Java
int      age    = 27;          // 32-bit integer
long     views  = 9_000_000L;  // 64-bit integer
double   pi     = 3.14159;     // 64-bit float
float    ratio  = 0.5f;        // 32-bit float
boolean  ready  = true;
char     grade  = 'A';
byte     flag   = 0x1F;
short    port   = 8080;

String   name   = "Ada";       // reference type
TIPThe 3D visualization shows stack frames on the left with primitives inline, and objects on the heap with arrows from stack references.
3D � stackHeap
KEY TAKEAWAYS
  • \u2713 8 primitives: byte, short, int, long, float, double, boolean, char.
  • \u2713 Primitives store the value; references store an address to a heap object.
  • \u2713 Use _ as a digit separator for readable large numbers.
1 � Foundations � lesson 4 of 41

Operators & Expressions

Arithmetic, comparison, logical and bitwise — and Java's promotion rules.

Java
int  sum   = 5 + 3;      // 8
int  div   = 7 / 2;      // 3  (integer division!)
double d   = 7 / 2.0;    // 3.5
int  mod   = 10 % 3;     // 1
boolean eq = (a == b);   // reference equality for objects
boolean ok = ready && !done;
int mask   = flags & 0xFF;   // bitwise AND
WATCH OUT== on Strings compares references, not content. Use .equals() to compare values.
KEY TAKEAWAYS
  • \u2713 Integer / integer = integer. Promote one side to get a double.
  • \u2713 && and || short-circuit; & and | do not (and also work bitwise).
  • \u2713 For objects, == checks identity, .equals() checks value.
1 � Foundations � lesson 5 of 41

Strings

Immutable text, the String pool, and how to concatenate efficiently.

String objects are immutable — every 'modification' creates a new object. Literals live in the String pool so identical literals share memory.

Java
String a = "Java";
String b = a + " 21";               // new object "Java 21"
String c = String.format("Hi %s!", a);

// Efficient repeated concatenation:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) sb.append(i);
String result = sb.toString();

// Text blocks (Java 15+):
String json = """
    { "name": "Ada" }
    """;
KEY TAKEAWAYS
  • \u2713 Strings are immutable — reuse literals from the pool for equality.
  • \u2713 Use StringBuilder inside loops instead of += concatenation.
  • \u2713 Text blocks (""") preserve multi-line formatting.
1 � Foundations � lesson 6 of 41

Reading Input

Scanner for the console, and a peek at System.in.

Java
import java.util.Scanner;

public class Ask {
    public static void main(String[] args) {
        try (Scanner in = new Scanner(System.in)) {
            System.out.print("Your name: ");
            String name = in.nextLine();
            System.out.println("Hello, " + name);
        }
    }
}
TIPtry-with-resources auto-closes the Scanner even if an exception is thrown.
KEY TAKEAWAYS
  • \u2713 Scanner wraps System.in for line/token/number reads.
  • \u2713 Close I/O resources — try-with-resources handles it for you.
2 � Control Flow & Methods � lesson 7 of 41

if / else

Branching with boolean expressions.

Java
if (score >= 90)      grade = 'A';
else if (score >= 80) grade = 'B';
else if (score >= 70) grade = 'C';
else                  grade = 'F';

String label = (age >= 18) ? "adult" : "minor";  // ternary
KEY TAKEAWAYS
  • \u2713 Conditions must be boolean.
  • \u2713 The ternary ?: is a compact if/else expression.
2 � Control Flow & Methods � lesson 8 of 41

switch & Pattern Switch

Classic switch statements and modern arrow-style expressions.

Java
// Modern switch expression (Java 14+)
String day = switch (n) {
    case 1, 7 -> "weekend";
    case 2, 3, 4, 5, 6 -> "weekday";
    default -> "unknown";
};

// Pattern switch (Java 21+)
String describe = switch (obj) {
    case Integer i when i > 0 -> "positive int " + i;
    case String  s            -> "string of length " + s.length();
    case null                 -> "nothing";
    default                   -> "something else";
};
KEY TAKEAWAYS
  • \u2713 Arrow switch expressions return values and have no fall-through.
  • \u2713 Pattern switch dispatches on the runtime type and can bind variables.
2 � Control Flow & Methods � lesson 9 of 41

Loops

for, while, do-while, and the for-each loop.

Java
for (int i = 0; i < 10; i++) { ... }

while (queue.hasNext()) { ... }

do { retry(); } while (!ok);

for (String name : names) {          // for-each
    System.out.println(name);
}
NOTEUse break to exit a loop early; continue skips to the next iteration.
KEY TAKEAWAYS
  • \u2713 for-each is the cleanest iteration over any Iterable.
  • \u2713 Prefer streams over manual loops for data transformations.
2 � Control Flow & Methods � lesson 10 of 41

Methods

Parameters, return types, and overloading.

Java
public static int max(int a, int b) {
    return a > b ? a : b;
}

// Overloading — same name, different parameters
public static double max(double a, double b) { ... }

// Varargs
public static int sum(int... nums) {
    int total = 0;
    for (int n : nums) total += n;
    return total;
}
KEY TAKEAWAYS
  • \u2713 Overloading picks the best-matching signature at compile time.
  • \u2713 Varargs (int... nums) is really an array under the hood.
2 � Control Flow & Methods � lesson 11 of 41

Recursion

A method that calls itself — and the stack frames it creates.

Java
static long factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}
WATCH OUTEach call pushes a new frame on the stack — too much recursion throws StackOverflowError.
3D � stackHeap
KEY TAKEAWAYS
  • \u2713 Every recursive call needs a base case.
  • \u2713 Watch the stack grow in the 3D visualization for factorial(5).
3 � Object-Oriented Core � lesson 12 of 41

Classes & Objects

State + behavior packaged together.

Java
public class Point {
    double x, y;                    // fields (state)

    double distance(Point other) {  // method (behavior)
        double dx = x - other.x, dy = y - other.y;
        return Math.sqrt(dx*dx + dy*dy);
    }
}

Point p = new Point();  // 'new' allocates on the heap
p.x = 3; p.y = 4;
3D � stackHeap
KEY TAKEAWAYS
  • \u2713 A class is a blueprint; an object is one instance in memory.
  • \u2713 'new' allocates a heap object and returns a reference.
3 � Object-Oriented Core � lesson 13 of 41

Constructors

How new objects are initialized.

Java
public class Point {
    final double x, y;

    public Point(double x, double y) {  // constructor
        this.x = x;
        this.y = y;
    }

    public Point() { this(0, 0); }      // chained constructor
}
KEY TAKEAWAYS
  • \u2713 Constructors have no return type and share the class name.
  • \u2713 this(...) chains to another constructor in the same class.
3 � Object-Oriented Core � lesson 14 of 41

this, static & final

Instance vs class members, and immutability.

Java
public class Counter {
    private static int total = 0;   // shared across all instances
    private final int id;           // set once per instance
    private int hits;

    public Counter() {
        this.id = ++total;
    }
    public static int totalCreated() { return total; }
}
  • \u25b8static members belong to the class, not any instance.
  • \u25b8final variables can be assigned only once.
  • \u25b8this refers to the current instance.
KEY TAKEAWAYS
  • \u2713 static = one copy per class.
  • \u2713 final = write-once.
3 � Object-Oriented Core � lesson 15 of 41

Inheritance

Extending a class to reuse and specialize.

Java
class Animal {
    String name;
    void speak() { System.out.println("..."); }
}

class Dog extends Animal {
    @Override
    void speak() { System.out.println(name + ": woof"); }
}

Animal a = new Dog();   // upcast
a.speak();              // dynamic dispatch \u2192 "woof"
TIPClick a node in the 3D class tree to highlight inherited members.
3D � inheritance
KEY TAKEAWAYS
  • \u2713 extends creates an 'is-a' relationship.
  • \u2713 @Override lets the compiler check you're really overriding.
  • \u2713 Method calls dispatch on the runtime type.
3 � Object-Oriented Core � lesson 16 of 41

Polymorphism

One interface, many runtime behaviors.

Java
Animal[] zoo = { new Dog(), new Cat(), new Cow() };
for (Animal a : zoo) a.speak();   // each speaks its own way
KEY TAKEAWAYS
  • \u2713 Program to the parent type; the JVM picks the right override.
  • \u2713 Enables 'open for extension, closed for modification' code.
3 � Object-Oriented Core � lesson 17 of 41

Abstract Classes

Partial blueprints that can't be instantiated.

Java
abstract class Shape {
    abstract double area();          // subclass must implement
    void describe() {
        System.out.println("area = " + area());
    }
}

class Circle extends Shape {
    double r;
    Circle(double r) { this.r = r; }
    double area() { return Math.PI * r * r; }
}
KEY TAKEAWAYS
  • \u2713 Use abstract when subclasses share code AND state.
  • \u2713 You cannot new an abstract class directly.
3 � Object-Oriented Core � lesson 18 of 41

Interfaces, Default & Sealed

Contracts with optional bodies, and restricted hierarchies.

Java
interface Drawable {
    void draw();
    default void redraw() {   // Java 8+ default method
        clear(); draw();
    }
    private void clear() { /* ... */ }
}

// Sealed (Java 17+) — only listed types may implement.
sealed interface Shape permits Circle, Square {}
final class Circle implements Shape {}
final class Square implements Shape {}
KEY TAKEAWAYS
  • \u2713 Interfaces are pure contracts; a class can implement many.
  • \u2713 default methods add behavior without breaking implementers.
  • \u2713 sealed types make pattern matching exhaustive.
4 � Data & Collections � lesson 19 of 41

Arrays

Fixed-size, contiguous, index-from-zero.

Java
int[] nums = new int[5];      // {0,0,0,0,0}
int[] primes = {2, 3, 5, 7, 11};
System.out.println(primes[2]);   // 5
System.out.println(primes.length);

int[][] grid = new int[3][3];    // multidimensional
WATCH OUTOut-of-range access throws ArrayIndexOutOfBoundsException.
3D � arrays
KEY TAKEAWAYS
  • \u2713 Length is fixed at creation.
  • \u2713 Multidim arrays are arrays of arrays.
4 � Data & Collections � lesson 20 of 41

ArrayList & LinkedList

The two workhorse Lists — and when to use each.

Java
import java.util.*;

List<String> names = new ArrayList<>();
names.add("Ada");
names.add("Grace");
names.remove(0);

List<Integer> queue = new LinkedList<>();
queue.add(1); queue.add(2);
  • \u25b8ArrayList: fast random access, slow inserts in the middle.
  • \u25b8LinkedList: fast head/tail inserts, slow random access.
KEY TAKEAWAYS
  • \u2713 Prefer ArrayList by default.
  • \u2713 Use List<T> as the declared type; swap implementations freely.
4 � Data & Collections � lesson 21 of 41

HashMap & HashSet

Key \u2192 value in O(1) average — using hashCode() and equals().

Java
Map<String, Integer> ages = new HashMap<>();
ages.put("Ada", 36);
ages.put("Grace", 85);
int a = ages.getOrDefault("Ada", 0);

for (var entry : ages.entrySet()) {
    System.out.println(entry.getKey() + " \u2192 " + entry.getValue());
}

Set<String> unique = new HashSet<>(List.of("a","b","a"));  // {a,b}
TIPThe 3D scene shows buckets: keys hash to a bucket index; collisions form a chain.
3D � hashmap
KEY TAKEAWAYS
  • \u2713 Custom keys must implement equals() AND hashCode() consistently.
  • \u2713 HashMap is unordered; use LinkedHashMap for insertion order.
4 � Data & Collections � lesson 22 of 41

Generics

Type parameters for reusable, type-safe containers.

Java
class Box<T> {
    private T value;
    public void set(T v) { value = v; }
    public T get() { return value; }
}

Box<Integer> b = new Box<>();
b.set(42);

// Bounded type parameter
static <T extends Comparable<T>> T max(T a, T b) {
    return a.compareTo(b) > 0 ? a : b;
}

List<? extends Number> readOnly;   // upper-bounded wildcard
KEY TAKEAWAYS
  • \u2713 Generics are erased at runtime — type checks happen at compile time.
  • \u2713 Use bounds (T extends X) to constrain what T can be.
4 � Data & Collections � lesson 23 of 41

Iterators & Iterable

The contract behind for-each.

Java
Iterator<String> it = names.iterator();
while (it.hasNext()) {
    String n = it.next();
    if (n.isEmpty()) it.remove();  // safe removal
}
KEY TAKEAWAYS
  • \u2713 for-each unrolls to iterator().hasNext()/next().
  • \u2713 Modifying a collection during for-each throws ConcurrentModificationException.
4 � Data & Collections � lesson 24 of 41

Comparable & Comparator

Natural order vs on-the-fly order.

Java
class User implements Comparable<User> {
    String name; int age;
    public int compareTo(User o) { return this.age - o.age; }
}

users.sort(Comparator.comparing((User u) -> u.name)
                     .thenComparingInt(u -> u.age).reversed());
KEY TAKEAWAYS
  • \u2713 Comparable defines the class's default order.
  • \u2713 Comparator lets you sort by any strategy at the call site.
5 � Intermediate � lesson 25 of 41

Exceptions & try-with-resources

Handling failure without cluttering happy paths.

Java
try (var reader = Files.newBufferedReader(path)) {
    return reader.readLine();
} catch (NoSuchFileException e) {
    return "";
} catch (IOException e) {
    throw new RuntimeException("read failed", e);
}

// Custom exception
class NotFoundException extends RuntimeException {
    public NotFoundException(String msg) { super(msg); }
}
  • \u25b8Checked exceptions (extends Exception) must be caught or declared.
  • \u25b8Unchecked (extends RuntimeException) don't require a throws clause.
  • \u25b8try-with-resources closes AutoCloseable resources in reverse order.
KEY TAKEAWAYS
  • \u2713 Catch narrow types first, wide types last.
  • \u2713 Always close I/O — let the compiler do it via try-with-resources.
5 � Intermediate � lesson 26 of 41

Enums

A fixed, type-safe set of named constants — that can also have behavior.

Java
enum Direction {
    NORTH( 0, -1), EAST(1, 0), SOUTH(0, 1), WEST(-1, 0);

    final int dx, dy;
    Direction(int dx, int dy) { this.dx = dx; this.dy = dy; }

    Direction opposite() {
        return values()[(ordinal() + 2) % 4];
    }
}
KEY TAKEAWAYS
  • \u2713 Enums can carry fields and methods.
  • \u2713 Prefer enums over public static final int for named sets.
5 � Intermediate � lesson 27 of 41

Records

Immutable data carriers with equals/hashCode/toString for free (Java 14+).

Java
record Point(double x, double y) {
    // compact constructor — validation
    public Point {
        if (Double.isNaN(x) || Double.isNaN(y))
            throw new IllegalArgumentException();
    }
    double distance(Point o) {
        return Math.hypot(x - o.x, y - o.y);
    }
}
KEY TAKEAWAYS
  • \u2713 Records are implicitly final and immutable.
  • \u2713 Fields become accessor methods: p.x() not p.x.
5 � Intermediate � lesson 28 of 41

Lambdas & Functional Interfaces

Passing behavior as data.

Java
Runnable r = () -> System.out.println("hi");
Function<String,Integer> len = s -> s.length();
BiFunction<Integer,Integer,Integer> add = (a, b) -> a + b;
Predicate<String> nonEmpty = s -> !s.isEmpty();

// Method reference
list.forEach(System.out::println);
KEY TAKEAWAYS
  • \u2713 A lambda targets a functional interface — one abstract method.
  • \u2713 Method references (Class::method) are compact lambda substitutes.
5 � Intermediate � lesson 29 of 41

Streams API

Declarative pipelines over collections.

Java
import java.util.stream.*;

int sum = List.of(1,2,3,4,5,6).stream()
    .filter(n -> n % 2 == 0)     // 2, 4, 6
    .mapToInt(Integer::intValue)
    .sum();                       // 12

Map<Boolean,List<Integer>> parts = IntStream.rangeClosed(1, 10)
    .boxed()
    .collect(Collectors.partitioningBy(n -> n % 2 == 0));
NOTEStreams are lazy — nothing happens until a terminal operation (sum, collect, forEach).
3D � streams
KEY TAKEAWAYS
  • \u2713 Stages: source \u2192 intermediate ops \u2192 terminal op.
  • \u2713 Streams are single-use; create a new one each time.
5 � Intermediate � lesson 30 of 41

Optional

A container that may or may not hold a value — a nicer alternative to null.

Java
Optional<User> found = repo.findById(42);
String name = found.map(u -> u.name).orElse("unknown");

found.ifPresent(u -> System.out.println(u.email));

// Chain
int emailLen = repo.findById(42)
    .map(u -> u.email)
    .map(String::length)
    .orElse(0);
WATCH OUTDon't use Optional for fields or parameters — reserve it for return types.
KEY TAKEAWAYS
  • \u2713 Signals absence in the type system.
  • \u2713 Use map/flatMap/orElse — avoid isPresent()+get().
5 � Intermediate � lesson 31 of 41

File I/O (NIO.2)

Modern paths, files and streams.

Java
import java.nio.file.*;
import java.nio.charset.StandardCharsets;

Path p = Path.of("notes.txt");
Files.writeString(p, "hello", StandardCharsets.UTF_8);
String text = Files.readString(p);
List<String> lines = Files.readAllLines(p);

try (var stream = Files.lines(p)) {
    stream.filter(l -> !l.isBlank()).forEach(System.out::println);
}
KEY TAKEAWAYS
  • \u2713 Prefer java.nio.file over the old java.io.File API.
  • \u2713 Files.lines() returns a lazy stream — close it.
5 � Intermediate � lesson 32 of 41

Packages & Modules

Namespaces for classes, and stronger boundaries between JAR-sized units.

Java
// File: com/acme/util/Math.java
package com.acme.util;

public class Math { ... }

// module-info.java (Java 9+)
module com.acme.util {
    exports com.acme.util;
    requires java.base;
}
KEY TAKEAWAYS
  • \u2713 Packages group related classes and are the unit of visibility.
  • \u2713 Modules add explicit exports/requires — stronger encapsulation than JARs.
6 � Advanced � lesson 33 of 41

Threads & Runnable

Multiple flows of execution inside one JVM.

Java
Thread t = new Thread(() -> {
    for (int i = 0; i < 5; i++)
        System.out.println("tick " + i);
});
t.start();       // runs concurrently
t.join();        // wait for it
TIPThe 3D scene shows two threads racing on a shared counter — watch it lose updates without synchronization.
3D � threads
KEY TAKEAWAYS
  • \u2713 start() spawns; run() would be sequential.
  • \u2713 Multiple threads share heap objects — that's where the trouble starts.
6 � Advanced � lesson 34 of 41

synchronized & Locks

Coordinating access so shared state stays consistent.

Java
class Counter {
    private int n;
    public synchronized void inc() { n++; }
    public synchronized int get() { return n; }
}

// Explicit lock
ReentrantLock lock = new ReentrantLock();
lock.lock();
try { /* critical section */ } finally { lock.unlock(); }
3D � threads
KEY TAKEAWAYS
  • \u2713 synchronized guarantees mutual exclusion and visibility.
  • \u2713 Prefer AtomicInteger / ConcurrentHashMap for simple cases.
6 � Advanced � lesson 35 of 41

ExecutorService

Thread pools — the right way to run many tasks.

Java
ExecutorService pool = Executors.newFixedThreadPool(4);

Future<Integer> f = pool.submit(() -> heavyWork());
Integer result = f.get();     // blocks until done

pool.shutdown();
KEY TAKEAWAYS
  • \u2713 Don't hand-roll threads — submit tasks to a pool.
  • \u2713 Always shutdown() the executor.
6 � Advanced � lesson 36 of 41

CompletableFuture

Composable async pipelines.

Java
CompletableFuture<String> page = CompletableFuture
    .supplyAsync(() -> fetch(url))
    .thenApply(String::trim)
    .thenCombine(
        CompletableFuture.supplyAsync(() -> fetch(url2)),
        (a, b) -> a + b)
    .exceptionally(err -> "fallback");

String result = page.join();
KEY TAKEAWAYS
  • \u2713 thenApply/thenCombine chain non-blocking steps.
  • \u2713 exceptionally / handle recover from failures.
6 � Advanced � lesson 37 of 41

Virtual Threads (Project Loom)

Millions of cheap threads scheduled on a few carriers (Java 21+).

Java
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < 1_000_000; i++) {
        exec.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return null;
        });
    }
}
NOTEVirtual threads are managed by the JVM, not the OS. Blocking is nearly free.
3D � virtualThreads
KEY TAKEAWAYS
  • \u2713 Write blocking code; the JVM parks/unparks the virtual thread.
  • \u2713 Great fit for I/O-heavy servers.
6 � Advanced � lesson 38 of 41

JVM Memory Model

Heap, stack, metaspace and how they interact.

  • \u25b8Stack — one per thread; primitives and references live here.
  • \u25b8Heap — shared across threads; all objects live here.
  • \u25b8Metaspace — class metadata, bytecode, method info.
  • \u25b8PC register + native method stack — bookkeeping per thread.
TIPThe 3D scene highlights the boundary: primitives are on the stack, objects float in the heap.
3D � stackHeap
KEY TAKEAWAYS
  • \u2713 Each thread gets its own stack.
  • \u2713 Only the heap is garbage-collected.
6 � Advanced � lesson 39 of 41

Garbage Collection

How unreachable objects are reclaimed.

Modern collectors (G1, ZGC, Shenandoah) divide the heap into generations. Most objects die young, so a fast 'minor GC' sweeps the young generation. Long-lived objects are promoted to the old generation, which is collected less often but more thoroughly.

Java
# Common tuning flags
-Xms512m -Xmx4g           # initial / max heap
-XX:+UseG1GC              # pick collector
-XX:+PrintGCDetails       # log GC
3D � gc
KEY TAKEAWAYS
  • \u2713 You don't free memory — you make objects unreachable.
  • \u2713 Young/old generations exploit the 'weak generational hypothesis'.
6 � Advanced � lesson 40 of 41

Reflection & Annotations

Inspecting and manipulating classes at runtime.

Java
Class<?> c = Class.forName("com.acme.User");
for (var m : c.getDeclaredMethods()) {
    System.out.println(m.getName());
}

// Custom annotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Benchmark { }

// Frameworks like Spring/JPA use reflection to wire your code.
KEY TAKEAWAYS
  • \u2713 Reflection powers frameworks — use it sparingly in app code.
  • \u2713 Annotations attach metadata for compile-time or runtime tools.
6 � Advanced � lesson 41 of 41

A Peek at Spring Boot

The most popular Java framework, in one file.

Java
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

@RestController
class HelloController {
    @GetMapping("/hello")
    String hello(@RequestParam String name) {
        return "Hello, " + name;
    }
}

Run it and http://localhost:8080/hello?name=Ada answers 'Hello, Ada'. Spring uses annotations + reflection to wire the controller, start an embedded Tomcat, and serve HTTP.

KEY TAKEAWAYS
  • \u2713 Convention over configuration — sensible defaults everywhere.
  • \u2713 Annotation-driven: @Service, @Repository, @Autowired, @Transactional.