Skip to main content

Java 21: 1 Hour Crash Course

Let’s embark on a journey to discover the most important parts of Java 21. I’ll cover the essentials, highlight new features in Java 21, and provide code samples and explanations. At the end of this article you’ll get a solid foundation and pointers for deeper study. Let's get started!



Java 21: 1 Hour Crash Course

1. Introduction

Java is a powerful, object-oriented programming language. Java 21, released in September 2023, brings performance improvements and new features.


Prerequisites:

  • Basic programming concepts (variables, loops, functions).

  • Java installed (JDK 21).

2. Your First Program


public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, Java 21!"); } }
  • public class HelloWorld — Defines a class.

  • public static void main — Entry point.

  • System.out.println — Prints to console.

3. Variables and Data Types


int age = 25; double price = 19.99; boolean isJavaFun = true; String name = "Java";

Primitive Types: intdoublebooleanchar
Reference Types: String, arrays, objects

4. Control Flow

If-Else


if (age > 18) { System.out.println("Adult"); } else { System.out.println("Minor"); }

Switch (Pattern Matching in Java 21!)


Object obj = "Hello"; switch (obj) { case String s -> System.out.println("String: " + s); case Integer i -> System.out.println("Integer: " + i); default -> System.out.println("Other type"); }

Loops


for (int i = 0; i < 5; i++) { System.out.println(i); } while (age < 30) { age++; }

5. Methods (Functions)


public static int add(int a, int b) { return a + b; }

Call: int sum = add(5, 3);

6. Classes and Objects


public class Person { String name; int age; public Person(String name, int age) { this.name = name; this.age = age; } public void greet() { System.out.println("Hi, I'm " + name); } } Person p = new Person("Alice", 30); p.greet();

7. Collections (Lists, Maps)


import java.util.*; List<String> names = new ArrayList<>(); names.add("Alice"); names.add("Bob"); Map<String, Integer> ages = new HashMap<>(); ages.put("Alice", 30); ages.put("Bob", 25);

8. Exception Handling


try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("Error: " + e.getMessage()); } finally { System.out.println("Done!"); }

9. Records (Java 16+, enhanced in Java 21)

    A record in Java is a special, concise class for immutable data. It automatically provides:

  • Private final fields for each component
  • Public accessor methods (getters) named after the fields
  • A canonical constructor
  • Implementations of equals()hashCode(), and toString()


public record Point(int x, int y) {} Point p = new Point(3, 4); System.out.println(p.x());

Key Properties:

  • All fields are final (immutable after creation)
  • The record itself is final (cannot be subclassed)
  • Designed for simple data carriers, not behavior-heavy classes

10. Sealed Classes (Java 17+, improved in Java 21)


public sealed interface Shape permits Circle, Square {} public final class Circle implements Shape {} public final class Square implements Shape {}

11. Pattern Matching for Switch (Java 21)

    Java 21 introduces record patterns, letting you easily extract data from records in instanceofchecks     and switch statements:

static void printType(Object obj) { switch (obj) { case String s -> System.out.println("String: " + s); case Integer i -> System.out.println("Integer: " + i); default -> System.out.println("Unknown type"); } }

    You can also use var for flexible variable names, and nest patterns for complex records.

    Advanced: Custom Constructors
    You can define custom constructors (canonical or non-canonical) for validation or default         values, but must call the canonical constructor

12. Virtual Threads (Project Loom, Java 21)


Thread.startVirtualThread(() -> { System.out.println("Hello from a virtual thread!"); });
  • Virtual threads are lightweight, making concurrent programming easier.


    Project Loom and Virtual Threads in Java 21

    Project Loom is a major enhancement to the Java platform that introduces virtual threads, a lightweight, high-scalability threading model aimed at simplifying concurrent programming and improving performance for I/O-bound and highly concurrent applications.

    What is Project Loom?

    Project Loom addresses the limitations of traditional Java threads, which are tied directly to operating system (OS) threads and are relatively heavy-weight. Traditional threads consume significant system resources and limit the number of concurrent threads an application can efficiently handle, typically to a few thousand.

    Project Loom introduces a new concept of virtual threads that are managed by the Java Virtual Machine (JVM) rather than the OS, allowing developers to create millions of concurrent threads efficiently. This enables a more straightforward, imperative style of concurrent programming without the complexity of asynchronous programming models.

    What are Virtual Threads?

    • Virtual threads are lightweight threads implemented by the JVM on top of a smaller pool of traditional OS-backed platform threads.

    • They extend java.lang.Thread but are not directly mapped to OS threads.

    • The JVM schedules virtual threads onto platform threads, which act as carrier threads.

    • When a virtual thread performs a blocking operation (e.g., I/O), the JVM unmounts it from the carrier platform thread, freeing that platform thread to run other virtual threads.

    • Once the blocking operation completes, the virtual thread is rescheduled on any available platform thread, allowing efficient use of resources.

    How Virtual Threads Work

    • The JVM maintains a fixed pool of platform threads (typically equal to the number of CPU cores).

    • Virtual threads are scheduled onto these platform threads dynamically.

    • When a virtual thread blocks, its stack state is saved to the heap, and the platform thread is freed to run other virtual threads.

    • This mechanism enables the JVM to handle many more concurrent threads than traditional threading models.

    Benefits of Virtual Threads in Java 21

    • Massive Scalability: Virtual threads can scale to hundreds of thousands or even millions of concurrent threads, far beyond the limits of platform threads.

    • Simplified Concurrency: Developers can write straightforward, imperative code using blocking calls without resorting to complex asynchronous programming.

    • Reduced Resource Usage: Virtual threads consume far less memory and CPU resources compared to traditional threads.

    • Improved Throughput: By freeing platform threads during blocking, applications can achieve higher throughput and better CPU utilization.

    • Seamless Integration: Virtual threads integrate with existing Java APIs and concurrency utilities, making adoption easier.

13. Enhanced String Templates (Preview in Java 21)

  Python had this feature, now java has it too! And I cannot be more happy. 
Not need to do ugly concatenations. Just simple and clean strings.

String name = "Alice"; int age = 30; String message = STR."Hello, \{name}. You are \{age} years old."; System.out.println(message);

14. Lambda Expressions and Streams

     No Change here :) Things stay exactly the same. 
I love how stream api has helped make java concise and reduce the LOC for any given logic. 
Java streams are magical. Just be careful not to compromise readability with over use of stream chaining. 
Add comments if you will.

List<String> names = List.of("Alice", "Bob", "Charlie"); names.stream() .filter(n -> n.startsWith("A")) .forEach(System.out::println);

15. Modules (Java 9+)


module com.example.myapp { requires java.base; }

16. Useful Tools

  • javac — Compile Java code

  • java — Run Java programs

  • jshell — Try Java code interactively


  • Summary Table

TopicKey Points / Example
Hello WorldSystem.out.println("Hello, Java 21!");
Variablesint x = 10; String s = "hi";
Control Flowifforswitch (pattern matching)
Methodspublic static int add(int a, int b)
Classes/Objectsclass Person { ... }
CollectionsList<String>Map<String, Integer>
Exception Handlingtry { ... } catch (Exception e) { ... }
Recordsrecord Point(int x, int y) {}
Sealed Classessealed interface Shape permits ...
Pattern Matchingswitch (obj) { case String s -> ... }
Virtual ThreadsThread.startVirtualThread(() -> { ... });
String TemplatesSTR."Hello, \{name}"
Lambdas/Streamsnames.stream().filter(...).forEach(...)

Hope this was helpful to you. For more such insightful articles follow this space. Please like and share if you found this article on linked in. Util next time, bye.

Comments

Popular posts from this blog

Intercommunication in the world of micro services

I always wondered what can be the different ways in which the microservices can commmunicate with each other. Like majority of us I almost instintively thought of REST or SOAP as two prominant ways of passing data over internet, but are there other better ways of making the different components of an enterprise systen talk to each other? If yes what is the purpose of their existance, lets address these and other related queries in this article. The manner in which micro services talk to each other can be classified in four major categories: Synchronous Communication Asynchronous Communication Database Level Communication Hybrid Lets explore them one by one -  Synchronous Communication In this style of inter service communication a sender service requests some resource from its counterpart and then waits for the response before proceeding ahead. This is also called blocking mode because the caller is blocked till it gets wahat it had requested. Lets explore some protocols which use ...

Spark Checkpointing,Union, Lineage And Partioning

I have been working on apache spark lately and wanted to consolidated my learnings at one place so that I can refer later and make it available to other developers as well. While working with spark you will often run into situations where the way you write code normally results in most inefficient results. You can visualise spark plan executions but it is very tedious to navigate and make sense of in terms of what exactly is cause of the problem. In such case having basic knowledge of how spark manages tasks can help arrive at solutions to improve compute efficiency. Below are a set of techniques I have used to improve compute efficiency of spark applications. SparkContext with a Checkpoint Directory In  Apache Spark , the  SparkContext  is the entry point to interact with the Spark framework. It manages the execution of jobs, resource allocation, and coordination across clusters. A  checkpoint directory  in Spark is used to store  checkpointed RDDs or stre...