Java is a statically-typed, class-based, compiled-to-bytecode language that runs on the Java Virtual Machine (JVM). It powers Android, large enterprise backends (Spring), big-data tools (Hadoop, Kafka), and most banking infrastructure. Part 1 of this two-part series covers the language core: from "hello world" through OOP, generics, exceptions, file I/O, and the basics of multithreading. Part 2 picks up with GUI, events, functional programming, collections, and the Stream API.
Learning Outcome
Compile and run Java programs with javac + java (and via an IDE).
Use primitives, wrappers, control flow, arrays, and strings idiomatically.
Define classes with constructors, fields, methods, access modifiers, and static.
Use inheritance, polymorphism, abstract classes, and interfaces.
Apply solid OOD principles (SOLID, encapsulation, composition over inheritance).
Write and use generic classes + methods.
Handle errors with try / catch / finally / throws and custom exceptions.
Use assert for development-time invariants.
Read and write files using the modern java.nio.file API.
Run code on multiple threads and recognise the standard concurrency utilities.
Chapter 1 — Introduction
Terminology
JDK — Java Development Kit: compiler + standard library + tools.
JRE — Java Runtime Environment: enough to run compiled code (rarely separated from JDK anymore).
JVM — Java Virtual Machine: executes bytecode.
Bytecode — the .class file format produced by javac.
Class — the template for objects.
Object — an instance of a class.
Package — a namespace; maps to a directory.
Main method — the JVM entry point: public static void main(String[] args).
Install
OS
Recommended
Any
Temurin (Eclipse Adoptium build of OpenJDK) — LTS 21 in 2026
macOS
brew install --cask temurin
Windows
winget install EclipseAdoptium.Temurin.21.JDK
Linux
sudo apt install openjdk-21-jdk (or distribution equivalent)
Verify:
1 2 3
java --version javac --version
Or use an IDE — IntelliJ IDEA Community is the standard pick.
try (varin= Files.newBufferedReader(Path.of("in.txt")); varout= Files.newBufferedWriter(Path.of("out.txt"))) { in.transferTo(out); } // both closed even on exception
Implementing AutoCloseable lets your own classes participate.
Custom exceptions
1 2 3 4 5 6
publicclassInsufficientFundsExceptionextendsRuntimeException { publicInsufficientFundsException(String msg) { super(msg); } } if (amount > balance) thrownewInsufficientFundsException("balance too low");
Trick: prefer unchecked exceptions for programming errors (bug-style: bad arg, missing key). Reserve checked exceptions for genuinely recoverable I/O. Modern Java style leans towards fewer checked exceptions.
Chapter 7 — Assertion
assert checks a development-time invariant. Disabled by default in production unless run with -ea (enable assertions).
1 2 3 4 5
publicintsqrt(int n) { assert n >= 0 : "n must be non-negative, got " + n; return (int) Math.sqrt(n); }
Trick: for most server workloads in 2026, Executors.newVirtualThreadPerTaskExecutor() + plain blocking code is the right answer. Reach for CompletableFuture only when you really need composition of async pipelines.
Practice Exercises
Exercise 1 — Class basics
Build a BankAccount class with deposit, withdraw (reject if overdraw), balance(). Override toString(). Add a transferTo(BankAccount other, double amount) method.
Exercise 2 — Inheritance
Define Shape (abstract double area()), Circle, Rectangle, Triangle. Put them in an array; print the total area.
Exercise 3 — Generics
Implement Stack<T> with push, pop, peek, isEmpty, size. Use an underlying ArrayList<T>.
Exercise 4 — Exception flow
Read a file path from args[0]; print its content. Catch NoSuchFileException and IOException separately, exit with different exit codes (2 and 3 respectively).
Spawn 1000 virtual threads, each downloading https://httpbin.org/uuid. Collect the responses into a List<String> (thread-safe!) and print the count of unique values.
Cheat-sheet
What
How
Compile
javac File.java
Run
java MainClass
Single-file run (modern)
java File.java
Class
public class Name { ... }
Record
public record Point(double x, double y) {}
Constructor
public Name(...) { this.x = ...; }
Override
@Override on method
Abstract class
public abstract class X { abstract void f(); }
Interface
public interface I { void f(); default void g() {} }
Generic class
class Box<T> { T value; }
Bounded generic
<T extends Comparable<T>>
Try with resources
try (var r = ...) { ... }
Read file
Files.readString(Path.of("..."))
Write file
Files.writeString(Path.of("..."), text)
Walk dir
Files.walk(Path.of("."))
Virtual thread
Thread.ofVirtual().start(runnable)
Virtual executor
Executors.newVirtualThreadPerTaskExecutor()
Sync method
public synchronized void f()
Atomic int
AtomicInteger
Thread-safe map
ConcurrentHashMap
What's next
Part 2 covers GUI (JavaFX), events, functional programming, the Collections framework, and the Stream API.
Modern Java in Action by Urma / Fusco / Mycroft — covers lambdas, streams, modules.
Note: this post is in progress. Planned additions: build tools (Maven, Gradle), modules (JPMS), sealed classes, pattern matching for switch, structured concurrency.