Java Course

Learn Java from the basics to concurrency: control flow, OOP, exceptions, generics, collections and streams, with real code examples and quizzes.

45 lessons in 8 categories

Java Basics

String

The first topic in the Java Basics category: `String`'s IMMUTABLE design, the string pool and the `==` vs `equals()` trap, the O(n^2) cost of `+` concatenation vs. `StringBuilder`'s amortized O(1) (with a real, warmed-up measurement), `String.format()`/text blocks (Java 15+), and helper methods like split/join/replace/trim/strip.

Beginner 20 min
Explore →

Arrays

The second topic in the Java Basics category: arrays' fixed-size, contiguous-memory structure, multi-dimensional arrays (including jagged arrays), the `Arrays` utility class (sort/binarySearch/equals/fill/copyOf), array covariance and the `ArrayStoreException` trap, `Arrays.asList()` being a view, and varargs.

Beginner 20 min
Explore →

Scanner

The third topic in the Java Basics category: `Scanner`'s token-based reading model, the classic `nextInt()` + `nextLine()` trap, custom delimiters via `useDelimiter()`, reading from a `File`, a real performance difference between `Scanner` and `BufferedReader`, and `InputMismatchException`/`NoSuchElementException` exception handling.

Beginner 20 min
Explore →

Wrapper Classes & Autoboxing

The fourth topic in the Java Basics category: the object counterparts of primitive types (Integer/Double/Boolean, etc.), autoboxing/autounboxing, Integer caching (-128..127) and the `==` trap, why unboxing a null wrapper throws a real NullPointerException, autoboxing's performance cost in tight loops, and how wrapper classes make generic collections possible.

Beginner 20 min
Explore →

File Reading

The fifth topic in the Java Basics category (the reading half of File I/O): `Path`/`Files` basics, `Files.readAllLines()`/`Files.readString()`, line-by-line reading with `BufferedReader`, `Files.lines()` being lazy and Closeable, searching a file for a word, and the real difference between `NoSuchFileException` and `FileNotFoundException`.

Beginner 20 min
Explore →

File Writing

The sixth topic in the Java Basics category (the writing half of File I/O): `Files.writeString()`/`Files.write()`, appending with `StandardOpenOption.APPEND`, writing with `BufferedWriter`, copying files with `Files.copy()`, `Files.createDirectories()`, the standard pattern for deleting a directory tree, and writing a CSV file.

Beginner 20 min
Explore →

Enum

A type-safe way to define a fixed set of constants in Java.

Beginner 35 min
Explore →

Record

Defining immutable data carriers in a single line in Java.

Intermediate 45 min
Explore →

Reflection

Accessing and dynamically using class, field, method, and constructor information at runtime in Java.

Advanced 50 min
Explore →

Date & Time API

The java.time package in Java; LocalDate/LocalTime/LocalDateTime, Instant, ZonedDateTime/OffsetDateTime, Duration/Period/ChronoUnit, formatting/parsing, time zones, and migrating from legacy Date/Calendar.

Intermediate 55 min
Explore →

Exceptions

Introduction to Exceptions

What an exception actually is -- why it exists (the problems with return-value-based error signaling), a short history of Java's checked exception design decision, the message/cause/stack trace an exception object carries, what happens when an exception goes uncaught, reading a stack trace and propagation, and the common runtime exception triggers (NullPointerException, ArrayIndexOutOfBoundsException, NumberFormatException). The first of 7 lessons in this series -- try/catch mechanics come next.

Beginner 20 min
Explore →

Try-Catch and Finally

The actual mechanism for handling an exception: the basic try-catch block, multiple catch blocks (matching in order, the superclass/subclass ordering restriction), multi-catch with | (Java 7+), finally running unconditionally every time, and how a return/throw inside finally silently overrides whatever try/catch was about to produce. The 2nd lesson in the Exception Handling series.

Beginner 20 min
Explore →

Exception Hierarchy

The inheritance relationship between Throwable, Error, Exception, and RuntimeException -- how every exception descends from a single shared root, how a catch block can target any ancestor of a type (polymorphic catching), and how to query that hierarchy at runtime with instanceof. The 3rd lesson in the Exception Handling series.

Beginner 20 min
Explore →

Checked vs Unchecked Exceptions

The difference between a checked exception's compiler-enforced throws/catch contract and an unchecked exception's (the RuntimeException family) complete lack of that requirement -- when to choose which, wrapping a checked exception as unchecked with the cause parameter, and the restriction that an overriding method's throws declaration can only be NARROWED. The 4th lesson in the Exception Handling series.

Beginner 20 min
Explore →

Throw and Throws

The difference between the throw statement handing a Throwable instance to the JVM at runtime and the throws declaration being a purely compile-time contract -- fail-fast validation, rethrowing a caught exception as a different type with the cause parameter, and a checked exception propagating unhandled through a call chain. The 5th lesson in the Exception Handling series.

Beginner 20 min
Explore →

Creating and Throwing Custom Exceptions

Defining your own exception type by extending Exception (checked) or RuntimeException (unchecked) -- adding fields that carry extra context, mirroring Throwable's four standard constructors, and building your own small exception hierarchy with a shared custom base class. The 6th lesson in the Exception Handling series.

Beginner 20 min
Explore →

Exception Handling Best Practices

Practices built on top of the previous six lessons' mechanics -- the anti-patterns of using exceptions for control flow and swallowing them, catching in the right order from specific to broad, and only catching where a genuinely useful response is possible. The 7th and final lesson in the Exception Handling series, closing with a recap of the whole series.

Beginner 20 min
Explore →

Generics

Introduction to Generics

Why generics exist (the pre-generics raw type/cast/ClassCastException problem), how type safety is enforced at compile time, generic classes and interfaces, and the type parameter naming convention. The 1st lesson in the Generics series.

Intermediate 25 min
Explore →

Generic Methods

Generic methods that declare their own type parameter independent of whether their class is generic -- method type parameters, multiple type parameters, type inference, and explicit type witnesses. The 2nd lesson in the Generics series.

Intermediate 20 min
Explore →

Bounded Type Parameters

Upper bounds (`<T extends ...>`), multiple bounds joined with `&`, bounding with classes and with interfaces, and how bounding a type parameter expands which methods can be called on it. The 3rd lesson in the Generics series.

Intermediate 20 min
Explore →

Wildcards

The unbounded wildcard (`<?>`), the upper bounded wildcard (`<? extends T>`), the lower bounded wildcard (`<? super T>`), the difference between the three, and the PECS (Producer Extends, Consumer Super) rule -- the most commonly misunderstood part of Java generics, walked through step by step with real examples. The 4th lesson in the Generics series.

Intermediate 30 min
Explore →

Generics with Collections

Generic collections like List<T>, Set<T>, and Map<K,V>, type safety with collections, why List<Object> is NOT List<String> (the full treatment of generics invariance), and type inference with the diamond operator and var. The 5th lesson in the Generics series.

Intermediate 25 min
Explore →

Type Erasure and Generic Limitations

What type erasure is, what happens to generic types at runtime, why `new T()` and generic arrays aren't allowed, static members and generics, and how generics' runtime limitations actually surface in practice (raw types, unchecked warnings, heap pollution). The 6th and final lesson in the Generics series.

Intermediate 25 min
Explore →

Control Flow

if / else

The first topic in the new Control Flow category: the basics of `if`/`else`, `else if` chains, nested conditions, the six comparison operators (`==`/`!=`/`<`/`>`/`<=`/`>=`) with decimal number and `String` comparison pitfalls, the `&&`/`||`/`!` logical operators and short-circuit evaluation, and the ternary operator.

Beginner 20 min
Explore →

switch

The second topic in the Control Flow category: classic `case`/`break` syntax and the fall-through trap, the modern arrow (`->`) syntax, switch EXPRESSIONS and `yield`, multiple labels with enum exhaustiveness checking, and using `switch` with `String`/enum.

Beginner 20 min
Explore →

for Loop

The third topic in the Control Flow category: the classic three-part (init;condition;update) `for` syntax, exiting early with `break`, skipping a step with `continue`, deliberate/unintentional infinite loops, multiple variables via comma-separated init/update, and classic index-based array iteration.

Beginner 20 min
Explore →

Enhanced for Loop

The fourth topic in the Control Flow category: the for-each syntax over arrays/collections, its three real limitations (no index access, the loop variable being a copy plus structural changes throwing ConcurrentModificationException, and no parallel iteration of multiple collections), and when to use it versus classic `for`.

Beginner 20 min
Explore →

while & do-while Loops

The fifth topic in the Control Flow category: basic `while` syntax, `do-while`'s run-at-least-once body, while vs do-while comparison, break/continue, a Scanner-based input validation loop, and a worked example: the Number Guessing Game.

Beginner 20 min
Explore →

Nested Loops

The sixth and final topic in the Control Flow category: basic nested for loops, 2D array traversal, how unlabeled break/continue only affect the innermost loop, labeled break/continue, and O(n²) performance awareness.

Beginner 22 min
Explore →

Collections

Lists

The first topic in the Collections category: the `List` interface, the performance difference between `ArrayList` and `LinkedList` shown with a real warmed-up measurement, immutable lists via `List.of()`/`Collections.unmodifiableList()`/`List.copyOf()`, safe iteration with `Iterator`/`ListIterator`, sorting with `List.sort(Comparator)`, and `subList()`/`toArray()`.

Beginner 20 min
Explore →

Sets

The second topic in the Collections category: the `Set` interface and its no-duplicates guarantee, the differences between `HashSet`/`LinkedHashSet`/`TreeSet`, `NavigableSet` methods, why the `equals()`/`hashCode()` contract is critical for `HashSet` (with a real bug example), set operations (union/intersection/difference), and a real performance measurement comparing List/HashSet/TreeSet.

Beginner 20 min
Explore →

Maps

The third topic in the Collections category: the `Map<K,V>` interface (each key once, mapped to a value), the differences between `HashMap`/`LinkedHashMap`/`TreeMap`, `NavigableMap` methods, immutable maps (`Map.of()`/`Map.copyOf()`), Java 8's modern API (`getOrDefault()`/`computeIfAbsent()`/`merge()`), and a real performance measurement comparing `entrySet()` and `keySet()+get()`.

Beginner 20 min
Explore →

Queues & Collections Utility

The final topic in the Collections category: the `Queue`/`Deque` interfaces (offer()/poll()/peek() vs add()/remove()/element()), why `ArrayDeque` is preferred over `LinkedList`/`java.util.Stack` as both a queue and a stack, a real discovery that `PriorityQueue` is heap-based and its toString() is NOT sorted, and the `Collections` utility class's static methods like sort/shuffle/max/binarySearch.

Beginner 20 min
Explore →

Object-Oriented Programming

Interface

Defining behavior contracts in Java; default/static/private methods and sealed interfaces.

Intermediate 50 min
Explore →

Abstract Class

Abstract classes that share common state and behavior in Java; constructors, the Template Method pattern, and abstract class vs interface.

Intermediate 50 min
Explore →

Inheritance

Inheritance in Java; extends, the constructor chain, method overriding, field hiding, upcasting/downcasting, and composition vs inheritance.

Intermediate 50 min
Explore →

Polymorphism

Polymorphism in Java; method overloading, overload resolution rules, covariant return types, polymorphism vs inheritance, and the Strategy pattern via composition.

Intermediate 45 min
Explore →

Concurrency

Threads

Threads in Java; creating threads (Thread/Runnable), the thread lifecycle, thread methods, race conditions, synchronized, volatile, wait/notify, Atomic classes, ReentrantLock, and deadlock.

Advanced 55 min
Explore →

Functional Interfaces & Streams

Lambda Expressions

The full syntax of lambda expressions: parameter-writing rules, expression body vs. block body, the compiler inferring a lambda's type from context (target typing), capturing effectively final variables, and how a lambda differs from an anonymous inner class.

Intermediate 20 min
Explore →

Built-in Functional Interfaces

The ready-made interfaces in java.util.function: Predicate<T>, Function<T,R>, Consumer<T>, Supplier<T>, UnaryOperator<T>, BinaryOperator<T>. The four method reference forms: Class::staticMethod, object::instanceMethod, Class::instanceMethod, Class::new.

Intermediate 22 min
Explore →

Stream API Fundamentals

The fundamentals of the Stream API: what a Stream is, moving from a Collection to a Stream, the three stages of a pipeline (source/intermediate/terminal). Intermediate operations: filter(), map(), flatMap(), distinct(), sorted(), peek(), limit(), skip(). Lazy evaluation and a stream's single-use nature.

Intermediate 25 min
Explore →

Terminal Operations

The terminal operations that trigger a stream pipeline and produce a result: forEach(), reduce(), count(), min()/max(), findFirst()/findAny(), anyMatch()/allMatch()/noneMatch(), toList()/toArray(). Short-circuiting behavior and count()'s source-size optimization.

Intermediate 22 min
Explore →

Collectors

The ready-made collect() recipes the Collectors class offers: toList()/toSet(), joining(), groupingBy() (with counting()/mapping() as downstream collectors), partitioningBy(), toMap(). The three parts of a Collector: supplier, accumulator, combiner.

Intermediate 22 min
Explore →

Optional

Optional<T>: expressing the possibility of an absent value in the type system. Creating with of()/ofNullable()/empty(), orElse() vs. orElseGet() (eager vs. lazy), orElseThrow(), map()/flatMap(), ifPresent()/ifPresentOrElse(), filter().

Intermediate 20 min
Explore →

Primitive & Parallel Streams

Avoiding autoboxing cost with IntStream/LongStream/DoubleStream, the boxed()/mapToInt() bridges. Running in parallel with parallelStream(), the forEach() vs. forEachOrdered() ordering difference, a non-thread-safe shared state pitfall, when to use it, and why it is not always faster.

Intermediate 25 min
Explore →