<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Felipe Stanzani</title>
    <description>The latest articles on DEV Community by Felipe Stanzani (@felipestanzani).</description>
    <link>https://dev.to/felipestanzani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1875141%2F2b2714dd-9166-4f0f-ab0c-e19fa7468b04.jpg</url>
      <title>DEV Community: Felipe Stanzani</title>
      <link>https://dev.to/felipestanzani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/felipestanzani"/>
    <language>en</language>
    <item>
      <title>Project Loom: Java's Virtual Threads – From Nightmares to Modern Concurrency Bliss</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Wed, 01 Apr 2026 20:21:49 +0000</pubDate>
      <link>https://dev.to/felipestanzani/project-loom-javas-virtual-threads-from-nightmares-to-modern-concurrency-bliss-3cm</link>
      <guid>https://dev.to/felipestanzani/project-loom-javas-virtual-threads-from-nightmares-to-modern-concurrency-bliss-3cm</guid>
      <description>&lt;p&gt;In 2006, I worked on a large logistics system for transporting wood for pulp production. One of the most critical modules managed the entry and exit of trucks from a storage yard. We implemented it using &lt;strong&gt;Threads in Delphi 7&lt;/strong&gt;. The debugging process was an absolute nightmare.&lt;/p&gt;

&lt;p&gt;Hundreds of trucks arriving and leaving, each one triggering database checks, sensor readings, queue management, and synchronization logic. Every thread was a heavyweight OS thread. Memory usage skyrocketed, context switching killed performance, and when something went wrong (which happened constantly), the debugger would freeze or show you a stack trace that made zero sense because the threads were all fighting for the same resources.&lt;/p&gt;

&lt;p&gt;Sound familiar?&lt;/p&gt;

&lt;p&gt;That exact pain — the same pain Java developers have felt for &lt;strong&gt;30 years&lt;/strong&gt; with regular &lt;code&gt;Thread&lt;/code&gt; objects and &lt;code&gt;ExecutorService&lt;/code&gt; backed by platform threads — is what &lt;strong&gt;Project Loom&lt;/strong&gt; was created to eliminate.&lt;/p&gt;

&lt;p&gt;Today, with Java 21+ (and fully mature in 2026), &lt;strong&gt;Virtual Threads&lt;/strong&gt; are production-ready and change the game completely.&lt;/p&gt;

&lt;p&gt;Let’s demystify Project Loom and see, with real Java code, why Virtual Threads are not just “better threads” — they are a completely different beast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Traditional (Platform) Threads
&lt;/h2&gt;

&lt;p&gt;Since Java 1.0, every &lt;code&gt;new Thread()&lt;/code&gt; or thread from a &lt;code&gt;ThreadPoolExecutor&lt;/code&gt; is a &lt;strong&gt;platform thread&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It maps &lt;strong&gt;one-to-one&lt;/strong&gt; to an OS thread.&lt;/li&gt;
&lt;li&gt;It consumes ~1 MB of stack space (configurable, but rarely less).&lt;/li&gt;
&lt;li&gt;Creating thousands of them is expensive and risky.&lt;/li&gt;
&lt;li&gt;Blocking operations (I/O, &lt;code&gt;sleep()&lt;/code&gt;, database calls, HTTP requests) block the &lt;strong&gt;entire OS thread&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Context switching is handled by the operating system (expensive).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the 2006 Delphi system, we could barely handle a few hundred concurrent trucks before the server started thrashing. The same limitation existed in Java until Project Loom.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classic Platform Thread Example (The Old Way)
&lt;/h3&gt;

&lt;p&gt;Here’s how we used to handle concurrent truck processing in Java (pre-Loom):&lt;/p&gt;

&lt;p&gt;&lt;em&gt;* All examples are in Java 25, you MUST enable preview features to execute them.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// OLD STYLE - Platform Threads&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TruckYardPlatformThreads&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ExecutorService&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newFixedThreadPool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Limited by OS&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// Imagine 10,000 trucks arriving&lt;/span&gt;
            &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;processTruck&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;truckId&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shutdown&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processTruck&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Truck #"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" entering yard [Thread: "&lt;/span&gt;
                               &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"]"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Simulate blocking I/O (database, sensor, loading/unloading)&lt;/span&gt;
            &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// This BLOCKS an entire OS thread!&lt;/span&gt;

            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Truck #"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" leaving yard"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;interrupt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problems with this code:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Maximum practical concurrency: ~200–500 threads on most servers.&lt;/li&gt;
&lt;li&gt;Memory usage: 200 threads × 1 MB stack = 200 MB just for stacks.&lt;/li&gt;
&lt;li&gt;Debugging deadlocks or race conditions? Good luck.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enter Project Loom and Virtual Threads
&lt;/h2&gt;

&lt;p&gt;Project Loom (started in 2017) introduced Virtual Threads — lightweight threads managed entirely by the JVM, not the OS.&lt;br&gt;
Key differences:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Platform Threads (Old)&lt;/th&gt;
&lt;th&gt;Virtual Threads (Loom)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mapping&lt;/td&gt;
&lt;td&gt;1:1 with OS thread&lt;/td&gt;
&lt;td&gt;Many:1 with carrier (platform) thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stack size&lt;/td&gt;
&lt;td&gt;~1 MB (fixed)&lt;/td&gt;
&lt;td&gt;"A few KB (dynamic, grows as needed)"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creation cost&lt;/td&gt;
&lt;td&gt;Expensive&lt;/td&gt;
&lt;td&gt;Extremely cheap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum practical count&lt;/td&gt;
&lt;td&gt;Thousands&lt;/td&gt;
&lt;td&gt;Millions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocking behavior&lt;/td&gt;
&lt;td&gt;Blocks OS thread&lt;/td&gt;
&lt;td&gt;Does not block carrier thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduling&lt;/td&gt;
&lt;td&gt;OS scheduler&lt;/td&gt;
&lt;td&gt;JVM scheduler (work-stealing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debugging experience&lt;/td&gt;
&lt;td&gt;Same as before&lt;/td&gt;
&lt;td&gt;Identical to platform threads&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Virtual threads are not a new abstraction like coroutines or reactive streams. They are real Thread objects — you can use &lt;code&gt;Thread.currentThread()&lt;/code&gt;, &lt;code&gt;synchronized&lt;/code&gt;, locks, &lt;code&gt;ThreadLocal&lt;/code&gt; (though &lt;code&gt;ScopedValue&lt;/code&gt; is preferred now), and they behave exactly like the threads you already know.&lt;/p&gt;

&lt;p&gt;The magic is under the hood: when a virtual thread blocks (e.g., &lt;code&gt;sleep()&lt;/code&gt;, I/O, waiting for a lock), the JVM unmounts it from its carrier thread and mounts another virtual thread. The carrier thread (a real OS thread) never blocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Virtual Threads – The New Way
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NEW STYLE - Virtual Threads (Java 21+)&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newVirtualThreadPerTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// ONE MILLION trucks? No problem!&lt;/span&gt;
        &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;processTruck&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;truckId&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Blocking calls like &lt;code&gt;Thread.sleep()&lt;/code&gt;, database queries, or HTTP requests no longer waste carrier threads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structured Concurrency (The Missing Piece)
&lt;/h2&gt;

&lt;p&gt;Project Loom also introduced Structured Concurrency (via &lt;code&gt;StructuredTaskScope&lt;/code&gt;), which makes concurrent code safer and more readable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Old way (fire-and-forget):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// OLD STYLE - Fire-and-forget with platform threads&lt;/span&gt;
&lt;span class="c1"&gt;// Hard to manage lifecycle, cancellation, and errors&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;processTruck&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Error handling is scattered and unreliable&lt;/span&gt;
            &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}).&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// No guarantee that threads will finish, no easy way to wait or cancel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach often leads to thread leaks, orphaned tasks, and difficult debugging — the same issues I faced 20 years ago in Delphi.&lt;/p&gt;

&lt;h3&gt;
  
  
  New way with Structured Concurrency:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NEW STYLE - Structured Concurrency with Virtual Threads&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;processTruckWithResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Truck #"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" entering yard [Virtual Thread: "&lt;/span&gt;
                       &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"]"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Simulate blocking work (DB, sensor, etc.)&lt;/span&gt;
    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Truck #"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" processed successfully"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StructuredTaskScope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;StructuredTaskScope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Joiner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allSuccessfulOrThrow&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StructuredTaskScope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Subtask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;subtasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;truckId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;subtasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fork&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;processTruckWithResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;truckId&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Wait for all subtasks&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;subtask&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subtasks&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Results are available and exceptions are propagated cleanly&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Scope automatically shuts down and cleans up all subtasks&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tasks are confined to a lexical scope (like try-with-resources for threads).&lt;/li&gt;
&lt;li&gt;If one task fails, remaining tasks are cancelled automatically.&lt;/li&gt;
&lt;li&gt;No thread leaks.&lt;/li&gt;
&lt;li&gt;Clear ownership and predictable lifecycle.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional Loom Features You Should Know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ScopedValue (modern, safer replacement for &lt;code&gt;ThreadLocal&lt;/code&gt; in many cases).&lt;/li&gt;
&lt;li&gt;Excellent backward compatibility — most existing thread-based code works with virtual threads with zero or minimal changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When Should You Use Virtual Threads?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use Virtual Threads when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Your application is I/O bound (web services, APIs, databases, logistics systems).&lt;/li&gt;
&lt;li&gt;You need high concurrency with simple code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Platform Threads (or combine) when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pure CPU-bound heavy computation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The 2006 logistics system I worked on would have been radically simpler and more reliable with Virtual Threads and Structured Concurrency. No more thread pool tuning nightmares. No more “out of threads” errors at 3 AM.&lt;/p&gt;

&lt;p&gt;Project Loom delivers scalable concurrency without forcing you to abandon the familiar threaded programming model.&lt;/p&gt;

&lt;p&gt;If you’re still managing fixed thread pools in 2026… it’s time to upgrade.&lt;/p&gt;

&lt;p&gt;Have you migrated any production systems to Virtual Threads yet? What was your experience?&lt;/p&gt;

&lt;p&gt;Drop your thoughts in the comments below. I’ll see you in the next post where we’ll explore Structured Concurrency and Scoped Values in much more depth.&lt;br&gt;
Until then — keep those memory leaks under control. 🚚&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://blog.felipestanzani.com/2026/04/01/project-loom-javas-virtual-threads-from-nightmares-to-modern-concurrency-bliss/" rel="noopener noreferrer"&gt;blog, Memory Leak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>performance</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Java 26: Pattern Matching Finally Reaches Primitive Types</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Thu, 19 Mar 2026 18:50:27 +0000</pubDate>
      <link>https://dev.to/felipestanzani/java-26-pattern-matching-finally-reaches-primitive-types-52gm</link>
      <guid>https://dev.to/felipestanzani/java-26-pattern-matching-finally-reaches-primitive-types-52gm</guid>
      <description>&lt;p&gt;Java has been evolving pattern matching for a while now. We got it for &lt;code&gt;instanceof&lt;/code&gt;, then for &lt;code&gt;switch&lt;/code&gt;, then for records. Each release pushed the idea a bit further. But there was always an odd limitation:&lt;/p&gt;

&lt;p&gt;Pattern matching worked great — as long as you stayed in the world of objects.&lt;/p&gt;

&lt;p&gt;Primitive types? Not invited.&lt;/p&gt;

&lt;p&gt;With Java 23, that gap is finally gone (as the first preview of this feature). This isn’t a flashy feature. It won’t generate “Java is reinvented” thumbnails. But it fixes something that has felt slightly off for years. In Java 26 we have the fourth preview of this feature, and it something that worth talking about.&lt;/p&gt;

&lt;p&gt;Let’s take a look at what changed — and why it actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Awkward Gap in Pattern Matching
&lt;/h2&gt;

&lt;p&gt;Before Java 23, pattern matching was strictly tied to reference types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works. But it comes with baggage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re dealing with Integer, not int&lt;/li&gt;
&lt;li&gt;There’s implicit unboxing&lt;/li&gt;
&lt;li&gt;The intent is slightly obscured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It gets worse when you realize that Java already has a rich set of primitive types — but pattern matching simply ignored them.&lt;/p&gt;

&lt;p&gt;So even in modern Java, you’d still end up writing code that feels… older than it should.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern Matching for Primitive Types
&lt;/h2&gt;

&lt;p&gt;Java 23 changes that by allowing primitive patterns directly in instanceof.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;intValue&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Now
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No wrapper. No manual unboxing. No extra noise.&lt;/p&gt;

&lt;p&gt;Just the value, in the form you actually want.&lt;/p&gt;

&lt;p&gt;What’s happening here is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The runtime checks whether the value can be represented as an int&lt;/li&gt;
&lt;li&gt;If it can, it binds it directly to a primitive variable&lt;/li&gt;
&lt;li&gt;If it can’t, the condition fails&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Gets Interesting
&lt;/h2&gt;

&lt;p&gt;On its own, this looks like a small improvement. But it becomes much more interesting when combined with other features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Matching Different Numeric Types
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10L&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"int: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"long: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you a clean way to refine types without bouncing through wrapper classes.&lt;/p&gt;

&lt;p&gt;You’re no longer matching objects that represent numbers. You’re matching the numbers themselves.&lt;/p&gt;

&lt;p&gt;Pattern Matching in switch&lt;/p&gt;

&lt;p&gt;This is where things start to feel really consistent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"int: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"long: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"double: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before Java 23, this kind of code simply wasn’t possible with primitives.&lt;/p&gt;

&lt;p&gt;Now it is — and it fits naturally with everything else pattern matching already does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conversions (With Some Rules)
&lt;/h3&gt;

&lt;p&gt;There’s also an important detail: not every numeric conversion will match.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// works (int → long)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10.5&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// does not match&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The general idea is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safe (widening) conversions may match&lt;/li&gt;
&lt;li&gt;Lossy (narrowing) conversions won’t&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps behavior predictable and avoids subtle bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Actually Matters
&lt;/h2&gt;

&lt;p&gt;This feature is easy to underestimate. It doesn’t introduce a new paradigm. It doesn’t change how you structure systems.&lt;/p&gt;

&lt;p&gt;But it removes friction in places where Java still felt unnecessarily verbose.&lt;/p&gt;

&lt;h3&gt;
  
  
  Less Boxing, Less Noise
&lt;/h3&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s a small change — but it aligns the code with what you actually care about.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Consistent Pattern Matching
&lt;/h3&gt;

&lt;p&gt;Java has been moving toward a unified pattern matching model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;instanceof patterns&lt;/li&gt;
&lt;li&gt;switch patterns&lt;/li&gt;
&lt;li&gt;record patterns&lt;/li&gt;
&lt;li&gt;deconstruction patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Primitive patterns were the missing piece.&lt;/p&gt;

&lt;p&gt;Now the model feels complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Fit for Real-World Code
&lt;/h3&gt;

&lt;p&gt;This becomes especially useful in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generic APIs dealing with Object&lt;/li&gt;
&lt;li&gt;Data processing pipelines&lt;/li&gt;
&lt;li&gt;Serialization/deserialization layers&lt;/li&gt;
&lt;li&gt;Switch-based dispatch logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anywhere values flow in a loosely typed way, this helps you regain type clarity without ceremony.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Few Things to Keep in Mind
&lt;/h2&gt;

&lt;p&gt;Even though this is straightforward, there are still a couple of rules worth remembering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not Every Conversion Works
&lt;/h3&gt;

&lt;p&gt;Be careful with narrowing conversions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;double → int&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;long → int&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If precision would be lost, the pattern simply won’t match.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don’t Get Clever for the Sake of It
&lt;/h3&gt;

&lt;p&gt;You can write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But like most modern Java features, the goal is clarity — not cleverness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts: A Small Feature That Fixes a Big Gap
&lt;/h2&gt;

&lt;p&gt;Pattern matching has been one of the most important evolutions in modern Java. But until now, it had a blind spot: primitives.&lt;/p&gt;

&lt;p&gt;Java 23 fixes that, and Java 26 bring it closer to a stable feature.&lt;/p&gt;

&lt;p&gt;No revolution. No paradigm shift. Just a missing piece finally added.&lt;/p&gt;

&lt;p&gt;And honestly, that’s very on-brand for Java. It doesn’t rush features out the door. It lets them mature, integrates them carefully, and eventually makes them feel like they’ve always been there. This is one of those cases.&lt;/p&gt;

&lt;p&gt;If you’re already using pattern matching heavily, this will feel like a natural extension. If you’re not, this might be the nudge that makes it click. Either way, it’s another step toward making Java code a little cleaner — and a little more honest about what it’s actually doing.&lt;/p&gt;

&lt;p&gt;What do you think? Is this something you see yourself using, or just another nice-to-have?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.felipestanzani.com/2026/03/19/java-26-pattern-matching-finally-reaches-primitive-types/" rel="noopener noreferrer"&gt;my blog, Memory Leak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>news</category>
      <category>java</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Java 25 After the Hype: 5 Features That Actually Matter</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Wed, 04 Mar 2026 18:00:11 +0000</pubDate>
      <link>https://dev.to/felipestanzani/java-25-after-the-hype-5-features-that-actually-matter-43gf</link>
      <guid>https://dev.to/felipestanzani/java-25-after-the-hype-5-features-that-actually-matter-43gf</guid>
      <description>&lt;p&gt;When a new Java version drops, the internet goes through its usual cycle: launch posts, conference talks, YouTube thumbnails screaming “GAME CHANGER,” and LinkedIn hot takes about how everything has changed forever.&lt;/p&gt;

&lt;p&gt;Then reality settles in.&lt;/p&gt;

&lt;p&gt;A few months after the release of Java 25, most teams aren’t rewriting their systems. They’re shipping features, fixing bugs, and trying to keep production stable. That’s when we can finally answer a more interesting question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which Java 25 features are still being discussed and actually used?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn’t a launch recap. This is a “post-hype” filter. Here are five Java 25 features that have proven they’re more than marketing bullets.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Structured Concurrency: Concurrency That Reads Like Logic (preview)
&lt;/h2&gt;

&lt;p&gt;For years, Java concurrency meant juggling &lt;code&gt;ExecutorService&lt;/code&gt;, &lt;code&gt;Future&lt;/code&gt;, timeouts, and cancellation semantics that were easy to get wrong.&lt;/p&gt;

&lt;p&gt;Structured Concurrency changes the mental model. Instead of spawning detached tasks and hoping everything is cleaned up properly, you treat concurrent tasks as a single logical unit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ExecutorService&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newFixedThreadPool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;userFuture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fetchUser&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="nc"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Orders&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ordersFuture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fetchOrders&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;Orders&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ordersFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’re responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cancellation&lt;/li&gt;
&lt;li&gt;Error propagation&lt;/li&gt;
&lt;li&gt;Proper shutdown&lt;/li&gt;
&lt;li&gt;Timeouts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  With Structured Concurrency
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StructuredTaskScope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ShutdownOnFailure&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fork&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fetchUser&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fork&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fetchOrders&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;throwIfFailed&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If one task fails, the others are cancelled.&lt;/li&gt;
&lt;li&gt;The lifecycle is explicit.&lt;/li&gt;
&lt;li&gt;The code reflects intent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it’s still relevant months later:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Because teams building high-throughput APIs, especially with virtual threads, are adopting it. It reduces subtle production bugs. This isn’t syntactic sugar — it’s operational sanity.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Scoped Values: A Safer Alternative to ThreadLocal
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ThreadLocal&lt;/code&gt; has been both useful and dangerous. It works — until you mix it with thread pools or forget to clean it up.&lt;/p&gt;

&lt;p&gt;Scoped Values offer a safer, more explicit model. They are immutable and bound to a dynamic scope.&lt;/p&gt;
&lt;h3&gt;
  
  
  Old Way (ThreadLocal)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;currentUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

&lt;span class="n"&gt;currentUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"felipe"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;processRequest&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;currentUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Easy to forget cleanup. Hard to reason about with thread reuse.&lt;/p&gt;
&lt;h3&gt;
  
  
  With Scoped Values
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ScopedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;CURRENT_USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ScopedValue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newInstance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;ScopedValue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CURRENT_USER&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"felipe"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
           &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;processRequest&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Immutable.&lt;/li&gt;
&lt;li&gt;Automatically scoped.&lt;/li&gt;
&lt;li&gt;No manual cleanup.&lt;/li&gt;
&lt;li&gt;Designed to work cleanly with virtual threads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it’s still in discussion:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Framework authors and library maintainers are actively evaluating it as a replacement for &lt;code&gt;ThreadLocal&lt;/code&gt; in request-scoped data. That alone makes it strategically important.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Generational Shenandoah GC: Practical Performance Gains
&lt;/h2&gt;

&lt;p&gt;Garbage Collection improvements don’t trend on X for long. But in production environments, they matter more than most language features.&lt;/p&gt;

&lt;p&gt;Generational Shenandoah combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low pause times&lt;/li&gt;
&lt;li&gt;Generational hypothesis (most objects die young)&lt;/li&gt;
&lt;li&gt;Large heap friendliness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For services with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High allocation rates&lt;/li&gt;
&lt;li&gt;Large heaps&lt;/li&gt;
&lt;li&gt;Strict latency requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…it’s a serious option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this one survived the hype cycle:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Because ops teams and performance engineers care. Lower pause times and better memory behavior translate directly into cost savings and more predictable latency.&lt;/p&gt;

&lt;p&gt;It’s not flashy — it’s practical.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Compact Object Headers: Memory Efficiency at Scale
&lt;/h2&gt;

&lt;p&gt;Compact Object Headers reduce the memory footprint of Java objects by shrinking object metadata.&lt;/p&gt;

&lt;p&gt;On small apps? You won’t notice.&lt;/p&gt;

&lt;p&gt;On:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-density containerized environments&lt;/li&gt;
&lt;li&gt;Large in-memory caches&lt;/li&gt;
&lt;li&gt;Massive object graphs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might.&lt;/p&gt;

&lt;p&gt;The benefit compounds when running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Microservices fleets&lt;/li&gt;
&lt;li&gt;Kubernetes clusters&lt;/li&gt;
&lt;li&gt;Cloud-native workloads with tight memory limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it still matters:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Because memory is money. And when you multiply small per-object savings by millions of objects, the math becomes real.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Pattern Matching Maturity: Primitive types on pattern matching (preview)
&lt;/h2&gt;

&lt;p&gt;Pattern matching has been evolving over the last releases, and Java 25 continues refining it, supporting primitive types (preview)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;myInt&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This is an int number:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;myInt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more casting noise. More expressive intent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it survived the hype:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Because it reduces friction in everyday code. This is the kind of incremental improvement that doesn’t make headlines but quietly improves developer experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts: Stability Is the Real Feature
&lt;/h2&gt;

&lt;p&gt;What truly defines its relevance months later isn’t that label — it’s which features teams actually keep using.&lt;/p&gt;

&lt;p&gt;The survivors tend to have three traits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They improve correctness (Structured Concurrency).&lt;/li&gt;
&lt;li&gt;They improve safety (Scoped Values).&lt;/li&gt;
&lt;li&gt;They improve performance (GC + memory changes).&lt;/li&gt;
&lt;li&gt;They reduce boilerplate without being gimmicky (Pattern Matching).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No revolutions. No paradigm shifts. Just steady refinement.&lt;/p&gt;

&lt;p&gt;And honestly? That’s why many of us are still here after decades.&lt;/p&gt;

&lt;p&gt;Java doesn’t chase trends. It absorbs what works, hardens it, and makes it boring in the best possible way.&lt;/p&gt;

&lt;p&gt;If you’ve already migrated to Java 25, what are you actually using in production? And if you haven’t upgraded yet, what’s holding you back?&lt;/p&gt;

&lt;p&gt;Let’s discuss.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://blog.felipestanzani.com/2026/03/04/java-25-after-the-hype/" rel="noopener noreferrer"&gt;blog, Memory Leak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>api</category>
      <category>java</category>
      <category>performance</category>
    </item>
    <item>
      <title>Spring Boot 4: Brief Upgrade Guide and Code Comparison</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Fri, 16 Jan 2026 20:33:49 +0000</pubDate>
      <link>https://dev.to/felipestanzani/spring-boot-4-brief-upgrade-guide-and-code-comparison-3io</link>
      <guid>https://dev.to/felipestanzani/spring-boot-4-brief-upgrade-guide-and-code-comparison-3io</guid>
      <description>&lt;p&gt;If you’ve been following my blog, you know I love a good migration story. Whether it’s moving to TanStack Start or refining shadcn/ui forms, the goal is always the same: better developer experience and more robust code.&lt;/p&gt;

&lt;p&gt;Today, we’re looking at the big one. &lt;strong&gt;Spring Boot 4.0&lt;/strong&gt; is officially out, and it’s arguably the most important release since 3.0. It moves the baseline to &amp;amp;&lt;strong&gt;Java 17&lt;/strong&gt; (with a massive push for &lt;strong&gt;Java 25&lt;/strong&gt;), adopts &lt;strong&gt;Jakarta EE 11&lt;/strong&gt;, and introduces features that finally kill off years of boilerplate.&lt;/p&gt;

&lt;p&gt;Let’s look at exactly what changed and how your code will look before and after the upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Native API Versioning
&lt;/h2&gt;

&lt;p&gt;For years, versioning an API in Spring meant custom URL paths, header filters, or complex &lt;code&gt;RequestCondition&lt;/code&gt; hacks. Spring Boot 4 brings this into the core framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Spring Boot 3 Way (Manual Pathing)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// You had to manually manage the path segments&lt;/span&gt;
&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/v1/orders"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderControllerV1&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/v2/orders"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderControllerV2&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Spring Boot 4 Way (Native Mapping)
&lt;/h3&gt;

&lt;p&gt;Now, versioning is a first-class citizen. You can keep the path clean and let Spring handle the routing logic via headers, query params, or path segments.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/orders"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;OrderV1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getOrdersV1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;OrderV2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getOrdersV2&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pro Tip: Configure the strategy in your &lt;code&gt;application.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.mvc.apiversion.use.header&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;X-API-Version&lt;/span&gt;
&lt;span class="py"&gt;spring.mvc.apiversion.default&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Declarative Resilience (No More Spring Retry)
&lt;/h2&gt;

&lt;p&gt;In the Spring Boot 3 era, you usually had to pull in the &lt;code&gt;spring-retry&lt;/code&gt; dependency and use &lt;code&gt;@EnableRetry&lt;/code&gt;. In Spring Boot 4, basic resilience patterns like Retry and Concurrency Limits are built directly into &lt;code&gt;spring-context&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring Boot 3 (Requires External Dependency)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Requires @EnableRetry in your config&lt;/span&gt;
&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StockService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Retryable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;NetworkException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;},&lt;/span&gt; &lt;span class="n"&gt;maxAttempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;updateStock&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Spring Boot 4 (Native &amp;amp; Robust)
&lt;/h3&gt;

&lt;p&gt;The new native &lt;code&gt;@Retryable&lt;/code&gt; and &lt;code&gt;@ConcurrencyLimit&lt;/code&gt; (Bulkhead pattern) work out of the box with the new &lt;code&gt;spring-boot-starter-resilience&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StockService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Retryable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;includes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NetworkException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@ConcurrencyLimit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Native Bulkhead pattern!&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;updateStock&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Automatically retries and limits concurrent threads&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Testing with RestTestClient
&lt;/h2&gt;

&lt;p&gt;Spring Framework 7 introduces &lt;code&gt;RestTestClient&lt;/code&gt;, which effectively replaces the choice between &lt;code&gt;MockMvc&lt;/code&gt; and &lt;code&gt;WebTestClient&lt;/code&gt; for most scenarios. It provides a single, fluent API that works for both mock environments and real running servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring Boot 3 (Choice of Two APIs)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// MockMvc for internal tests or WebTestClient for reactive/live&lt;/span&gt;
&lt;span class="nd"&gt;@Autowired&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;MockMvc&lt;/span&gt; &lt;span class="n"&gt;mockMvc&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;mockMvc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;perform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;andExpect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isOk&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Spring Boot 4 (Unified Fluent API)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Autowired&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;RestTestClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testHello&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;expectStatus&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isOk&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;expectBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Architectural Modularization
&lt;/h2&gt;

&lt;p&gt;Spring Boot 4 has undergone a "diet." &lt;code&gt;The internal spring-boot-autoconfigure&lt;/code&gt; JAR has been split into dozens of smaller, technology-specific modules.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Spring Boot 3&lt;/th&gt;
&lt;th&gt;Spring Boot 4&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Auto-config&lt;/td&gt;
&lt;td&gt;Monolithic autoconfigure.jar&lt;/td&gt;
&lt;td&gt;Small, focused modules (e.g., spring-boot-autoconfigure-data-jpa)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOT / Native&lt;/td&gt;
&lt;td&gt;Basic GraalVM support&lt;/td&gt;
&lt;td&gt;Optimized GraalVM 25 support with lower memory footprint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Startup&lt;/td&gt;
&lt;td&gt;Slower due to classpath scanning&lt;/td&gt;
&lt;td&gt;Faster build/boot via modular hints&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you notice missing auto-configurations after upgrading, you may need to add a specific starter for that technology (e.g., &lt;code&gt;spring-boot-starter-flyway&lt;/code&gt; instead of just the Flyway core JAR).&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Type Safety: The JSpecify Shift
&lt;/h2&gt;

&lt;p&gt;Null safety is no longer a "suggestion." Spring Boot 4 fully adopts JSpecify. This isn't just a new set of annotations; it changes how Kotlin and static analysis tools view your code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spring Boot 3: Used a mix of &lt;code&gt;@Nullable&lt;/code&gt; from various packages (JSR-305, JetBrains).&lt;/li&gt;
&lt;li&gt;Spring Boot 4: Standardizes on &lt;code&gt;org.jspecify.annotations&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts: The Road to Java 25
&lt;/h2&gt;

&lt;p&gt;While the baseline is Java 17, the real magic of Spring Boot 4 happens on Java 25. With virtual threads enabled (&lt;code&gt;spring.threads.virtual.enabled=true&lt;/code&gt;), the framework optimizes internal task executors to use lightweight threads, making your blocking code perform like reactive code without the complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ready to migrate?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Move to &lt;strong&gt;Spring Boot 3.5&lt;/strong&gt; first - &lt;em&gt;if you are not already there&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Fix all deprecation warnings (especially around &lt;code&gt;RestTemplate&lt;/code&gt; and old Actuator properties).&lt;/li&gt;
&lt;li&gt;Flip the switch to &lt;strong&gt;Spring Boot 4.0&lt;/strong&gt; and enjoy a leaner, safer backend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What’s your favorite new feature? I’m personally voting for native API versioning—it's about five years overdue! Let me know in the comments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.felipestanzani.com/2026/01/16/spring-boot-4-brief-upgrade-guide-and-code-comparison/" rel="noopener noreferrer"&gt;my blog - Memory Leak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>architecture</category>
      <category>learning</category>
    </item>
    <item>
      <title>JSON is Making You Lose Money!!!</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Sun, 02 Nov 2025 14:20:05 +0000</pubDate>
      <link>https://dev.to/felipestanzani/json-is-making-you-lose-money-4i58</link>
      <guid>https://dev.to/felipestanzani/json-is-making-you-lose-money-4i58</guid>
      <description>&lt;p&gt;Let's be real: every time you shove a bloated JSON blob into an LLM prompt, you're literally &lt;strong&gt;burning cash&lt;/strong&gt;. Those curly braces, endless quotes, and repeated keys? They're token vampires sucking your OpenAI/Anthropic/Cursor bill dry. I've been there – cramming user data, analytics, or repo stats into prompts, only to hit context limits or watch costs skyrocket.&lt;/p&gt;

&lt;p&gt;But what if I told you there's a format that &lt;strong&gt;cuts tokens by up to 60%&lt;/strong&gt;, boosts LLM accuracy, and was cleverly designed for exactly this problem? Meet &lt;strong&gt;TOON&lt;/strong&gt; (Token-Oriented Object Notation), the brainchild of &lt;a href="https://byjohann.link/" rel="noopener noreferrer"&gt;Johann Schopplich&lt;/a&gt; – a dev who's all about making AI engineering smarter and cheaper.&lt;/p&gt;

&lt;p&gt;Johann nailed it with TOON over at his original TypeScript repo: &lt;a href="https://github.com/johannschopplich/toon" rel="noopener noreferrer"&gt;github.com/johannschopplich/toon&lt;/a&gt;. It's not just another serialization format; it's a lifeline for anyone building AI apps at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why JSON is Robbing You Blind in LLM Prompts
&lt;/h2&gt;

&lt;p&gt;JSON is great for APIs and config files. But for LLM context? It's a disaster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verbose AF&lt;/strong&gt;: Braces &lt;code&gt;{}&lt;/code&gt;, brackets &lt;code&gt;[]&lt;/code&gt;, quotes around every key and string – all eating tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repeated Keys&lt;/strong&gt;: In arrays of objects, every row repeats the same field names. 100 users? That's 100x "id", "name", etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Built-in Smarts&lt;/strong&gt;: LLMs have to parse all that noise, leading to higher error rates on retrieval tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Explosion at Scale&lt;/strong&gt;: A modest dataset can balloon to thousands of unnecessary tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result? Higher costs, slower responses, and more "context too long" errors. If you're querying GPT-5-nano or Claude with tabular data, JSON is quietly making you poor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter TOON: The Token-Slaying Hero
&lt;/h2&gt;

&lt;p&gt;TOON flips the script by blending YAML's clean indentation with CSV's tabular efficiency – but optimized for LLMs. Key differences from JSON:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tabular Arrays&lt;/strong&gt;: Declare fields once in a header, then stream rows comma/tab/pipe-separated. No repeating keys!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal Punctuation&lt;/strong&gt;: Ditches braces/brackets/quotes where possible. Indentation handles nesting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit Lengths&lt;/strong&gt;: &lt;code&gt;[N]&lt;/code&gt; prefixes arrays so LLMs know exactly what's coming – reduces parsing errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Quoting&lt;/strong&gt;: Only quotes when needed (e.g., strings with delimiters or specials).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delimiter Options&lt;/strong&gt;: Comma (default), tab, or pipe for extra token wins (tabs often tokenize best).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TOON shines on &lt;strong&gt;uniform arrays of objects&lt;/strong&gt; – think user lists, analytics rows, or GitHub repos. For non-uniform or deeply nested data, it gracefully falls back to list format (still slimmer than JSON).&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Examples: JSON vs TOON
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Classic JSON Bloat&lt;/strong&gt; (257 tokens for a tiny e-commerce order):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sku"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"qty"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;9.99&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sku"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"B2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"qty"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;14.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;TOON Magic&lt;/strong&gt; (166 tokens – 35% savings):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;items[2]{sku,qty,price}&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;A1,2,9.99&lt;/span&gt;
  &lt;span class="s"&gt;B2,1,14.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nested? No problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;orders[1]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;users[2]{id,name}&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="s"&gt;1,Ada&lt;/span&gt;
      &lt;span class="s"&gt;2,Bob&lt;/span&gt;
    &lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;active&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Primitive arrays inline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;tags[3]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admin,ops,dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for wonky data, it uses clean lists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;mixed[3]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ada&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quoted,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;string"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benchmarks That'll Make You Switch Today
&lt;/h2&gt;

&lt;p&gt;Johann's rigorous tests (using GPT-5 tokenizer) across real datasets prove TOON crushes JSON:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repos&lt;/strong&gt; (top 100): 8,745 tokens vs JSON's 15,145 (&lt;strong&gt;42% saved&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Analytics&lt;/strong&gt; (180 days): 4,507 vs 10,977 (&lt;strong&gt;59% saved&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E-Commerce Orders&lt;/strong&gt;: 166 vs 257 (&lt;strong&gt;35% saved&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total&lt;/strong&gt;: 13,418 vs 26,379 (&lt;strong&gt;49% average savings&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accuracy? TOON hits &lt;strong&gt;70%+&lt;/strong&gt; on retrieval tasks across GPT-5, Claude, Gemini, and Grok – often beating JSON while using half the tokens. Check the full spec for details: &lt;a href="https://github.com/johannschopplich/toon/blob/main/SPEC.md" rel="noopener noreferrer"&gt;TOON Spec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pro tip: Use tab delimiters for even more savings on big tables!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-On: TOON in TypeScript (The OG)
&lt;/h2&gt;

&lt;p&gt;Install the original:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @toon-format/toon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Encode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;encode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@toon-format/toon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;delimiter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt; &lt;span class="c1"&gt;// Tab for extra savings!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;users[2 ]{id    name    role}&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;1 Alice   admin&lt;/span&gt;
  &lt;span class="s"&gt;2 Bob user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Decode back to JS objects too. CLI for quick conversions: &lt;code&gt;npx @toon-format/cli data.json --stats&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TOON in Java: Meet JToon (My port)
&lt;/h2&gt;

&lt;p&gt;Java devs rejoice! &lt;a href="https://github.com/felipestanzani/JToon" rel="noopener noreferrer"&gt;JToon&lt;/a&gt; brings TOON to the JVM – Maven Central ready.&lt;/p&gt;

&lt;p&gt;Add it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.felipestanzani&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;jtoon&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;0.1.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.felipestanzani.jtoon.JToon&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.felipestanzani.jtoon.Delimiter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.felipestanzani.jtoon.EncodeOptions&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;sku&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;qty&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;9.99&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"B2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;14.5&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EncodeOptions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Delimiter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TAB&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Tabs + length markers&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JToon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;items[#2 ]{sku qty price}&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;A1 2 &lt;/span&gt;&lt;span class="m"&gt;9.99&lt;/span&gt;
  &lt;span class="s"&gt;B2 1 &lt;/span&gt;&lt;span class="m"&gt;14.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even encodes JSON strings directly: &lt;code&gt;JToon.encodeJson(jsonString)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TOON Everywhere: Ports Galore
&lt;/h2&gt;

&lt;p&gt;TOON's spec is open and crystal-clear, so ports are popping up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript/JS&lt;/strong&gt; (original): &lt;a href="https://github.com/johannschopplich/toon" rel="noopener noreferrer"&gt;github.com/johannschopplich/toon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java&lt;/strong&gt; (JToon – battle-tested): &lt;a href="https://github.com/felipestanzani/JToon" rel="noopener noreferrer"&gt;github.com/felipestanzani/JToon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.NET:&lt;/strong&gt; &lt;a href="https://github.com/0xZunia/ToonSharp" rel="noopener noreferrer"&gt;ToonSharp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crystal:&lt;/strong&gt; &lt;a href="https://github.com/mamantoha/toon-crystal" rel="noopener noreferrer"&gt;toon-crystal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dart:&lt;/strong&gt; &lt;a href="https://github.com/wisamidris77/toon" rel="noopener noreferrer"&gt;toon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elixir:&lt;/strong&gt; &lt;a href="https://github.com/kentaro/toon_ex" rel="noopener noreferrer"&gt;toon_ex&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gleam:&lt;/strong&gt; &lt;a href="https://github.com/axelbellec/toon_codec" rel="noopener noreferrer"&gt;toon_codec&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go:&lt;/strong&gt; &lt;a href="https://github.com/alpkeskin/gotoon" rel="noopener noreferrer"&gt;gotoon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCaml:&lt;/strong&gt; &lt;a href="https://github.com/davesnx/ocaml-toon" rel="noopener noreferrer"&gt;ocaml-toon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP:&lt;/strong&gt; &lt;a href="https://github.com/HelgeSverre/toon-php" rel="noopener noreferrer"&gt;toon-php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python:&lt;/strong&gt; &lt;a href="https://github.com/xaviviro/python-toon" rel="noopener noreferrer"&gt;python-toon&lt;/a&gt; or &lt;a href="https://github.com/bpradana/pytoon" rel="noopener noreferrer"&gt;pytoon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruby:&lt;/strong&gt; &lt;a href="https://github.com/andrepcg/toon-ruby" rel="noopener noreferrer"&gt;toon-ruby&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust:&lt;/strong&gt; &lt;a href="https://github.com/shreyasbhat0/rtoon" rel="noopener noreferrer"&gt;rtoon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swift:&lt;/strong&gt; &lt;a href="https://github.com/mattt/TOONEncoder" rel="noopener noreferrer"&gt;TOONEncoder&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pick your poison and start saving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop Losing Money – Switch to TOON Now
&lt;/h2&gt;

&lt;p&gt;JSON had its time. For LLM prompts, TOON is the future: cheaper, faster, more accurate. Thank Johann Schopplich for this gem – follow him at &lt;a href="https://byjohann.link/" rel="noopener noreferrer"&gt;byjohann.link&lt;/a&gt; for more AI wizardry.&lt;/p&gt;

&lt;p&gt;Try it in your next prompt. Your wallet (and your LLMs) will thank you. What's your biggest token horror story? Drop it in the comments – and share this if you're tired of JSON waste!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Originally posted on my &lt;a href="https://blog.felipestanzani.com/2025/11/02/json-is-making-you-lose-money/" rel="noopener noreferrer"&gt;blog, Memory Leak&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Demystifying Object-Oriented Programming: Pt. 2</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Thu, 09 Oct 2025 12:04:29 +0000</pubDate>
      <link>https://dev.to/felipestanzani/demystifying-object-oriented-programming-pt-2-40d1</link>
      <guid>https://dev.to/felipestanzani/demystifying-object-oriented-programming-pt-2-40d1</guid>
      <description>&lt;p&gt;Welcome back! At the end of our last post, we hit a bit of a roadblock. We had successfully organized our &lt;code&gt;F1&lt;/code&gt;, &lt;code&gt;PickupTruck&lt;/code&gt;, and &lt;code&gt;SUV&lt;/code&gt; classes to inherit from a base &lt;code&gt;Car&lt;/code&gt; class. But then, we were faced with a new challenge:&lt;/p&gt;

&lt;p&gt;A bicycle, a speedboat, and an electric car. They are all vehicles, but trying to force them into a single &lt;code&gt;Vehicle&lt;/code&gt; inheritance hierarchy would be a nightmare. A speedboat doesn't have wheels, and a bicycle doesn't have an engine in the traditional sense. A simple &lt;code&gt;extends Vehicle&lt;/code&gt; starts to feel clunky and wrong. How do we model things that share behaviors but are fundamentally different things?&lt;/p&gt;

&lt;p&gt;The answer lies in moving beyond the idea that everything must share a common ancestor and instead thinking about what they can &lt;strong&gt;DO&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interfaces: A Contract of Behavior
&lt;/h2&gt;

&lt;p&gt;Let’s ask a different question. Instead of asking what these objects are, let's ask what they have in common from a user's perspective. A person can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Steer them&lt;/li&gt;
&lt;li&gt;Make them go forward&lt;/li&gt;
&lt;li&gt;Slow them down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Object-Oriented Programming, when we want to guarantee that different classes share a common set of behaviors, we use an &lt;strong&gt;INTERFACE&lt;/strong&gt;. Think of an interface not as a blueprint for an object, but as a contract. It’s a list of methods that a class promises to implement. It defines &lt;strong&gt;WHAT&lt;/strong&gt; a class can do, but not &lt;strong&gt;HOW&lt;/strong&gt; it does it.&lt;/p&gt;

&lt;p&gt;Let's create a contract for anything that can be driven. We'll call it &lt;code&gt;Drivable&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interface&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnLeft&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnRight&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;brake&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice a few things. We use the &lt;code&gt;interface&lt;/code&gt; keyword, not &lt;code&gt;class&lt;/code&gt;. And the methods have no body—no &lt;code&gt;{}&lt;/code&gt; with code inside. The Drivable interface simply states: "Any class that wants to be considered &lt;code&gt;Drivable&lt;/code&gt; &lt;strong&gt;MUST&lt;/strong&gt; provide its own implementation for these four methods."&lt;/p&gt;

&lt;p&gt;Now, our classes can sign this contract using the &lt;code&gt;implements&lt;/code&gt; keyword.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... all the car attributes&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Code to make the engine burn fuel and turn the wheels&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ... other Drivable methods implemented&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bicycle&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... bicycle attributes like pedals, handlebars&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Code that represents the rider pedaling faster&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ... other Drivable methods implemented&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Speedboat&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... speedboat attributes like hull, propeller&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Code to engage the propeller and push water&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ... other Drivable methods implemented&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With interfaces, we've solved our problem! We haven’t forced a bicycle to have an engine, or a car to have a propeller. We simply grouped them by a common capability: being drivable. A class can also implement multiple interfaces. A modern smart car could be &lt;code&gt;Drivable&lt;/code&gt;, &lt;code&gt;ConnectableToInternet&lt;/code&gt;, and &lt;code&gt;HasGPS&lt;/code&gt;, for example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polymorphism: One Action, Many Forms
&lt;/h2&gt;

&lt;p&gt;This leads us to one of the most powerful concepts in OOP: POLYMORPHISM. The word literally means "many forms." It’s the ability to treat objects of different classes as if they were the same type, as long as they adhere to the same contract (interface).&lt;/p&gt;

&lt;p&gt;Imagine you have a garage. You can put all your drivable things in it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="n"&gt;mySuv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;SUV&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="n"&gt;myBike&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bicycle&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="n"&gt;myBoat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Speedboat&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Drivable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;garage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;garage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mySuv&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;garage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myBike&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;garage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myBoat&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the magic. We can loop through our garage and tell everything to accelerate, and each object will know how to perform that action in its own unique way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;garage&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;vehicle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// The SUV roars, the bike pedals, the boat throttles up!&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is polymorphism in action. The same method call, &lt;code&gt;vehicle.accelerate()&lt;/code&gt;, produces entirely different results depending on the actual object. You, the programmer, don’t need to know or care what type of object it is at that moment. You only need to know that it’s &lt;code&gt;Drivable&lt;/code&gt; and can therefore &lt;code&gt;accelerate&lt;/code&gt;. This makes your code incredibly flexible and easy to extend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstract Classes: The Best of Both Worlds?
&lt;/h2&gt;

&lt;p&gt;So, are interfaces the solution to everything? Not quite. Sometimes, you have a group of classes that are very closely related—they really do share a common identity and implementation, not just a behavior.&lt;/p&gt;

&lt;p&gt;Let's go back to our &lt;code&gt;Car&lt;/code&gt; example. We have gasoline cars, electric cars, and hybrid cars. They are all fundamentally cars. They all share a chassis, wheels, and a steering mechanism that works the same way. It would be wasteful to re-write the &lt;code&gt;turnLeft&lt;/code&gt; method for every single type of car.&lt;/p&gt;

&lt;p&gt;This is where an &lt;strong&gt;ABSTRACT CLASS&lt;/strong&gt; comes in. An abstract class is a hybrid between a regular class and an interface.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Like a class, it can have attributes and fully implemented methods.&lt;/li&gt;
&lt;li&gt;Like an interface, it can have &lt;code&gt;abstract&lt;/code&gt; methods that have no implementation.&lt;/li&gt;
&lt;li&gt;You cannot create an instance of an abstract class directly (you can't build a generic "Car," only a specific type like an &lt;code&gt;ElectricCar&lt;/code&gt;).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Attributes all cars share&lt;/span&gt;
  &lt;span class="nc"&gt;Chassis&lt;/span&gt; &lt;span class="n"&gt;chassis&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nc"&gt;Wheel&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;wheels&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// A concrete method that all subclasses will inherit&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnLeft&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// The logic for turning is the same for all cars&lt;/span&gt;
  &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Turning left."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// An abstract method that subclasses MUST implement&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;refuel&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, specific car types can &lt;code&gt;extend&lt;/code&gt; this abstract class. They inherit the &lt;code&gt;chassis&lt;/code&gt;, &lt;code&gt;wheels&lt;/code&gt;, and the &lt;code&gt;turnLeft&lt;/code&gt; method for free, but they are forced to provide their own logic for &lt;code&gt;refuel&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GasolineCar&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;refuel&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pumping gasoline."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ElectricCar&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;refuel&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Plugging into charging station."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Interface vs. Abstract Class: When to Use Which?
&lt;/h2&gt;

&lt;p&gt;This is a classic question, but the distinction is clear once you grasp the core idea.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use an &lt;strong&gt;Abstract Class&lt;/strong&gt; for objects that are closely related in an "is-a" relationship. An &lt;code&gt;ElectricCar&lt;/code&gt; is a &lt;code&gt;Car&lt;/code&gt;. It allows you to share common code and attributes among a family of classes. A class can only &lt;code&gt;extend&lt;/code&gt; &lt;strong&gt;one&lt;/strong&gt; abstract class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use an &lt;strong&gt;Interface&lt;/strong&gt; for objects that share a common capability, often in a "can-do" relationship. A &lt;code&gt;Car&lt;/code&gt; can be &lt;code&gt;Drivable&lt;/code&gt;. A &lt;code&gt;Drone&lt;/code&gt; can be &lt;code&gt;Flyable&lt;/code&gt;. A &lt;code&gt;SmartSpeaker&lt;/code&gt; can be &lt;code&gt;ConnectableToInternet&lt;/code&gt;. A &lt;code&gt;class&lt;/code&gt; can &lt;code&gt;implement&lt;/code&gt; &lt;strong&gt;many&lt;/strong&gt; interfaces.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Today, we've added three more powerful concepts to our OOP toolkit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interface: A contract defining behaviors (what it &lt;strong&gt;CAN DO&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Polymorphism: Treating different objects as the same type, allowing one action to have many forms.&lt;/li&gt;
&lt;li&gt;Abstract Class: A partial blueprint for a family of related classes, sharing common code (what &lt;strong&gt;IT IS&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By understanding when to use inheritance, abstract classes, and interfaces, you can build software that is flexible, reusable, and much easier to manage. You can now model complex relationships without tying yourself in knots.&lt;/p&gt;

&lt;p&gt;What are your thoughts? Have you struggled with these concepts before? Leave your comments, suggestions, and questions below. See you in the next post!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://blog.felipestanzani.com/2025/10/09/demystifying-object-oriented-programming-pt-2/" rel="noopener noreferrer"&gt;blog, Memory Leak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>java</category>
      <category>learning</category>
    </item>
    <item>
      <title>[Updated] Seamless Forms with shadcn/ui and TanStack Form</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Fri, 26 Sep 2025 21:21:22 +0000</pubDate>
      <link>https://dev.to/felipestanzani/seamless-forms-with-shadcnui-and-tanstack-form-mng</link>
      <guid>https://dev.to/felipestanzani/seamless-forms-with-shadcnui-and-tanstack-form-mng</guid>
      <description>&lt;p&gt;In my post, &lt;a href=""&gt;"Life after Next.js: A New and Sunny Start,"&lt;/a&gt; I talked about my journey migrating to TanStack Start and the freedom it brought. One of the loose ends I mentioned was the form situation. I'm a big fan of the aesthetics and developer experience of &lt;a href="https://ui.shadcn.com/" rel="noopener noreferrer"&gt;shadcn/ui&lt;/a&gt;, but its default form component is built on react-hook-form. As I'm going all-in on the TanStack ecosystem, I naturally wanted to use &lt;a href="https://tanstack.com/form" rel="noopener noreferrer"&gt;TanStack Form&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This presented a classic developer dilemma: do I stick with a component that doesn't quite fit my new stack, or do I build something better? The answer was obvious. I couldn't find a clean, existing solution that married the beauty of shadcn/ui with the power and type-safety of TanStack Form. So, I decided to build it myself.&lt;/p&gt;

&lt;p&gt;Today, I'm excited to share the result: a component that seamlessly integrates shadcn/ui with TanStack Form, preserving the core principles of both libraries. It's type-safe, easy to use, and maintains that clean shadcn/ui look and feel.&lt;/p&gt;

&lt;p&gt;You can check out the component's &lt;a href="https://shadcn-tanstack-form.felipestanzani.com" rel="noopener noreferrer"&gt;website&lt;/a&gt; and find the full source code on the &lt;a href="https://github.com/felipestanzani/shadcn-tanstack-form" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bother?
&lt;/h2&gt;

&lt;p&gt;TanStack Form offers incredible power with its framework-agnostic, type-safe approach to form state management. shadcn/ui, on the other hand, provides beautiful, accessible, and unopinionated components. The goal was to get the best of both worlds without any compromises. This component acts as the bridge, giving you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full Type-Safety: Infer types directly from your validation schemas (like Zod, Valibot, etc.).&lt;/li&gt;
&lt;li&gt;Seamless TanStack Integration: Leverage TanStack Form’s state management and validation logic.&lt;/li&gt;
&lt;li&gt;Consistent shadcn/ui Styling: Use the form components you already know and love.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Get Started
&lt;/h2&gt;

&lt;p&gt;Setting it up is straightforward. Follow these steps, and you'll have type-safe, beautiful forms up and running in minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install shadcn/ui
&lt;/h3&gt;

&lt;p&gt;If you haven't already, initialize shadcn/ui in your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx shadcn-ui@latest init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Install TanStack Form
&lt;/h3&gt;

&lt;p&gt;Next, add the TanStack Form library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @tanstack/react-form
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Copy the Core Components
&lt;/h3&gt;

&lt;p&gt;My solution consists of two key files. Download them from the GitHub repository and place them in the correct folders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;form.tsx: &lt;a href="https://github.com/felipestanzani/shadcn-tanstack-form/blob/main/src/components/ui/form.tsx" rel="noopener noreferrer"&gt;Copy this&lt;/a&gt; to your components/ui folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;form-hook.tsx: &lt;a href="https://github.com/felipestanzani/shadcn-tanstack-form/blob/main/src/hooks/form-hook.tsx" rel="noopener noreferrer"&gt;Copy this&lt;/a&gt; to a hooks folder in your project's root.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Add shadcn/ui Components
&lt;/h3&gt;

&lt;p&gt;Finally, add the shadcn/ui components you'll need for your forms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx shadcn-ui@latest add button input label form
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Use It
&lt;/h2&gt;

&lt;p&gt;Once installed, using the component is intuitive. The structure will feel very familiar to anyone who has used shadcn/ui's original form component.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Define your Form Logic
&lt;/h3&gt;

&lt;p&gt;First, define your form's schema (using Zod in this example) and create the form instance with the &lt;code&gt;useAppForm&lt;/code&gt; hook. Here you'll set default values, validators, and your &lt;code&gt;onSubmit&lt;/code&gt; handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAppForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/hooks/form-hook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid email address&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyFormComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;defaultValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Build the Form Component
&lt;/h3&gt;

&lt;p&gt;Now, construct your form using the components provided. The &lt;code&gt;&amp;lt;form.AppForm&amp;gt;&lt;/code&gt; component links your form instance, and &lt;code&gt;&amp;lt;form.AppField&amp;gt;&lt;/code&gt; connects each input to the form state.&lt;/p&gt;

&lt;p&gt;Here’s a complete example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAppForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/hooks/form-hook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/ui/button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/ui/input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FieldLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FieldControl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FieldDescription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FieldError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/ui/form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid email address&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;EmailForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;defaultValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Pretend to submit for 500ms&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AppForm&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Form&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;space-y-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AppField&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FieldLabel&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FieldLabel&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FieldControl&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Input&lt;/span&gt;
                  &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                  &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                  &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
                  &lt;span class="nx"&gt;onBlur&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleBlur&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FieldControl&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FieldDescription&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`We'll never share your email with anyone else.`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FieldDescription&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FieldError&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Field&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form.AppField&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Subscribe&lt;/span&gt;
          &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canSubmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSubmitting&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;{([&lt;/span&gt;&lt;span class="nx"&gt;canSubmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isSubmitting&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;canSubmit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isSubmitting&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Submitting...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form.Subscribe&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form.AppForm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, &lt;code&gt;&amp;lt;form.Subscribe&amp;gt;&lt;/code&gt; allows you to listen to the form's state, which is perfect for disabling the submit button while the form is invalid or submitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This component was born out of a real need in my own project, and I believe it can help others who find themselves in the same boat. It provides a clean, robust, and type-safe solution for building forms without having to choose between a great state manager and a great component library.&lt;/p&gt;

&lt;p&gt;Give it a try in your next project! I'd love to hear your feedback. Feel free to open an issue or pull request on the GitHub repository. What are your go-to solutions for forms in React? Let me know in the comments below!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://blog.felipestanzani.com/2025/09/26/seamless-forms-with-shadcn-ui-and-tanstack-form/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>react</category>
    </item>
    <item>
      <title>JavaScript in 2025: New Stable Features to Boost Your Code</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Sat, 19 Jul 2025 13:36:52 +0000</pubDate>
      <link>https://dev.to/felipestanzani/javascript-in-2025-new-stable-features-to-boost-your-code-5hjm</link>
      <guid>https://dev.to/felipestanzani/javascript-in-2025-new-stable-features-to-boost-your-code-5hjm</guid>
      <description>&lt;p&gt;Hey there! JavaScript became 30 years old in 2025. Despite being created for browsers’ front-end code, it gained more space than expected in the backend. ECMAScript 2025 (ES16), released in June, brought a handful of stable features that make coding smoother without forcing you to kneel before the latest framework altar. In this post, I’ll walk you through the standout additions with practical examples, and for each, I’ll show how you’d do the same thing the old-school way — pre-ES2025. Spoiler: the new features save you some headaches, but the fundamentals still hold strong. Let’s dive in, no fluff, just code!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Iterator Helpers: Functional Programming Without the Headache
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What’s New&lt;/strong&gt;: Iterator Helpers introduce a global Iterator object that lets you chain operations like &lt;code&gt;.map()&lt;/code&gt; and &lt;code&gt;.filter()&lt;/code&gt; on any iterable (arrays, sets, generators) in a memory-efficient, lazy way. It’s functional programming without the bloat of intermediate arrays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example with Iterator Helpers&lt;/strong&gt;: Filtering and transforming a leaderboard of scores.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;topScores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;scores&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Score: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;topScores&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ["Score: 100%", "Score: 85%", "Score: 90%", "Score: 95%"]&lt;/span&gt;

&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// After ES2025&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;topScores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Score: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;topScores&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ["Score: 100%", "Score: 85%", "Score: 90%", "Score: 95%"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why the New Way Wins&lt;/strong&gt;: The Iterator approach is lazy, processing elements one at a time without creating temporary arrays, which is a lifesaver for large datasets. The old-school array method is simpler to read but can be less performant when chaining multiple operations. That said, for small arrays, the difference is negligible—don’t overcomplicate things just because you can.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: Stick to arrays for quick tasks, but use Iterator when performance matters or when working with non-array iterables like generators.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. New Set Methods: Set Theory, Meet JavaScript
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What’s New&lt;/strong&gt;: ES2025 adds methods like intersection, union, and difference to Set, making it easier to perform set operations without clunky workarounds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example with New Set Methods&lt;/strong&gt;: Finding shared songs between two playlists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playlistA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bohemian Rhapsody&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Imagine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Smells Like Teen Spirit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playlistB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Imagine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hotel California&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bohemian Rhapsody&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sharedSongs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;playlistA&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;song&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;playlistB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;song&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;sharedSongs&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// ['Bohemian Rhapsody', 'Imagine']&lt;/span&gt;

&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// After ES2025&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playlistA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bohemian Rhapsody&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Imagine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Smells Like Teen Spirit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playlistB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Imagine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hotel California&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bohemian Rhapsody&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sharedSongs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playlistA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;playlistB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;sharedSongs&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// ['Bohemian Rhapsody', 'Imagine']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why the New Way Wins&lt;/strong&gt;: The intersection method is more readable and expressive, directly conveying intent. The old-school approach requires converting the set to an array and back, which is less elegant and slightly less performant for large sets. Still, the old way works fine for simple cases—don’t rewrite your code just to use the new shiny.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch Out&lt;/strong&gt;: Sets are for unique values. If you need ordered lists or complex data, arrays or objects are still your friends.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. JSON Modules: Importing JSON Without the Fuss
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What’s New&lt;/strong&gt;: ES2025’s JSON Modules let you import JSON files as modules with a simple import statement, using &lt;code&gt;{ type: 'json' }&lt;/code&gt;. No more fetch or require hacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example with JSON Modules&lt;/strong&gt;: Importing a config file for a dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;

&lt;span class="c1"&gt;// Browser example with fetch&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'dark'&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ['bar', 'line']&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Node.js example with require&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'dark'&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ['bar', 'line']&lt;/span&gt;

&lt;span class="c1"&gt;////////////////////////////////&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// After ES2025&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;

&lt;span class="c1"&gt;// config.json&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;charts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// app.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'dark'&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ['bar', 'line']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why the New Way Wins&lt;/strong&gt;: JSON Modules are cleaner and synchronous (no async boilerplate), making them ideal for static configs. The fetch approach requires async/await, which can complicate simple use cases, and require is Node-specific, breaking in browsers without a bundler. That said, fetch is still necessary for dynamic or remote JSON.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caveat&lt;/strong&gt;: Browser support is at 87% (mid-2025). For older environments, stick with fetch or use a bundler like Vite for polyfills.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Promise.try: Simplifying Promise Wrappers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What’s New&lt;/strong&gt;: Promise.try wraps any function (sync or async) in a Promise, catching errors and returning a resolved or rejected Promise. It’s a cleaner way to unify sync and async code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example with Promise.try&lt;/strong&gt;: Validating user input that might throw an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;validateInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Input cannot be empty!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runValidation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;validateInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'HELLO'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'Input cannot be empty!'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;runValidation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;runValidation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//////////////////////////////&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// After ES2025&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;validateInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Input cannot be empty!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;validateInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'HELLO'&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;validateInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'Input cannot be empty!'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why the New Way Wins&lt;/strong&gt;: Promise.try is concise, eliminating the verbose new Promise wrapper and unifying error handling for sync and async code. The old-school approach works but is clunkier, especially when mixing sync and async logic. Still, if you’re already in an async context, a simple try-catch might suffice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think Twice&lt;/strong&gt;: Don’t overuse Promise.try for straightforward async functions—async/await is often cleaner.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. RegExp.escape: Goodbye, Manual String Escaping
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What’s New&lt;/strong&gt;: RegExp.escape escapes special regex characters in a string, making it safe for use in a RegExp constructor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example with RegExp.escape&lt;/strong&gt;: Matching user input literally in a search feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;escapeRegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;.*+?^${}()|[&lt;/span&gt;&lt;span class="se"&gt;\]\\]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;$&amp;amp;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello.world*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;escaped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;escapeRegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'hello\.world\*'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;escaped&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello.world* is awesome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="c1"&gt;////////////////////////////////&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// After ES2025&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello.world*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;escaped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'hello\.world\*'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;escaped&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello.world* is awesome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why the New Way Wins&lt;/strong&gt;: RegExp.escape is a built-in, reliable solution that saves you from writing (and debugging) your own escape function. The old-school method works but requires maintaining extra code, which can be error-prone if you miss a special character.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heads-Up&lt;/strong&gt;: This is niche but invaluable for dynamic regex patterns, like search or validation logic. If you rarely build regexes from user input, you might not need it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts: New Tools, Same Fundamentals
&lt;/h3&gt;

&lt;p&gt;ES2025’s Iterator Helpers, Set methods, JSON Modules, &lt;code&gt;Promise.try&lt;/code&gt;, and &lt;code&gt;RegExp.escape&lt;/code&gt; are practical additions that streamline common tasks without reinventing the wheel. Compared to the old-school approaches, they offer cleaner syntax, better performance (in some cases), and less boilerplate. But let’s not get carried away — these are tools, not magic bullets. The old ways still work, and sometimes they’re simpler for small projects or when you need broad compatibility.&lt;/p&gt;

&lt;p&gt;As always, my advice is to experiment with these features but stay grounded in the fundamentals: write code that solves problems, not code that chases trends. Don’t let the hype on X or at tech conferences trick you into thinking you need to rewrite everything to “stay modern.” JavaScript’s beauty is in its flexibility — and the problems too.&lt;/p&gt;

&lt;p&gt;Got thoughts on ES2025? Tried these features or stuck with the classics? Drop a comment below, and let’s geek out over what JavaScript’s doing in 2025!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted in my &lt;a href="https://blog.felipestanzani.com/2025/07/18/javascript-2025-new-stable-features-to-boost-your-code/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>news</category>
    </item>
    <item>
      <title>Demystifying Object-Oriented Programming: Pt. 1</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Mon, 07 Jul 2025 23:18:35 +0000</pubDate>
      <link>https://dev.to/felipestanzani/demystifying-object-oriented-programming-pt-1-3g0</link>
      <guid>https://dev.to/felipestanzani/demystifying-object-oriented-programming-pt-1-3g0</guid>
      <description>&lt;h2&gt;
  
  
  The Misconception of Object-Oriented Programming
&lt;/h2&gt;

&lt;p&gt;When we think about object-oriented programming, we often relate it to real-world objects. The problem is this: associating object-oriented programming with tangible real-world things doesn’t work in 80% of cases, and this brings more difficulties than clarity for beginners.&lt;/p&gt;

&lt;p&gt;Back in 1996, when I started programming in Delphi 4, its biggest competitor was Visual Basic, but Delphi was OBJECT-ORIENTED. If I had stopped at that programming course, I still wouldn't have known what this famous object-oriented programming was, and neither would the course instructor.&lt;/p&gt;

&lt;p&gt;I worked at various companies and on commercial software projects in Delphi that were far from truly using object-oriented programming. Most Delphi programmers I met thought object-oriented programming was about dragging a button onto a screen, double-clicking it, and creating a function for that button, for example.&lt;/p&gt;

&lt;p&gt;So, let’s talk about what object-oriented programming REALLY is.&lt;/p&gt;

&lt;p&gt;First, look at the image below and tell me what you see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftycnbks4jiqi5ei933gc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftycnbks4jiqi5ei933gc.png" alt="An F1, a Pickup Truck, and an SUV" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obviously, you see three cars: a pickup truck, an F1 car, and an SUV. The important question is: if these cars are so different, how do you know they are all cars? What makes a car a car and not a table or a piano?&lt;/p&gt;

&lt;p&gt;There’s a concept of what a car is that’s already ingrained in your mind. A car IS LIKE THIS and SERVES THIS PURPOSE. In object-oriented programming, this concept that defines what a car is called a CLASS: it’s the definition of WHAT a certain object is. The car you touch, the one you drive from point A to point B, is what we call an OBJECT. It’s the materialized concept. This materialized concept is technically called an INSTANCE. That’s why you’ll sometimes read that an object is an instance of a class. Always translate this as: the object you touch is a concept that has been materialized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining a Car: Attributes and the Blueprint of a Class
&lt;/h2&gt;

&lt;p&gt;So, imagine you want to build a car from scratch. You’d take the car’s blueprint, a plan, and build that car. This blueprint is the Class; it defines WHAT the car is and HOW IT WORKS.&lt;/p&gt;

&lt;p&gt;Let’s describe WHAT a car is. A car:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has a chassis&lt;/li&gt;
&lt;li&gt;Has an engine&lt;/li&gt;
&lt;li&gt;Has wheels and tires&lt;/li&gt;
&lt;li&gt;Has a steering wheel&lt;/li&gt;
&lt;li&gt;Has a gear shifter&lt;/li&gt;
&lt;li&gt;Has a driver’s seat&lt;/li&gt;
&lt;li&gt;Has an accelerator&lt;/li&gt;
&lt;li&gt;Has a brake&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maybe I didn’t list everything that defines a car because I forgot something, but let’s agree that not every car has a body, headlights, a clutch pedal, doors, mirrors, seat belts, or air conditioning, yet it’s still a car. Can a golf cart not be classified as a car? What about an electric car? Or a car from the 1920s? We’ll come back to this later, but there’s a basic concept of what a car is, and there are specific concepts for specific cars. Our basic class with attributes looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Class&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Attributes&lt;/span&gt;
    &lt;span class="nc"&gt;Chassis&lt;/span&gt; &lt;span class="n"&gt;chassis&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Engine&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Wheel&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;wheels&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;SteeringWheel&lt;/span&gt; &lt;span class="n"&gt;steeringWheel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;GearShifter&lt;/span&gt; &lt;span class="n"&gt;gearShifter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;DriverSeat&lt;/span&gt; &lt;span class="n"&gt;driverSeat&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Accelerator&lt;/span&gt; &lt;span class="n"&gt;accelerator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Brake&lt;/span&gt; &lt;span class="n"&gt;brake&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the car’s attributes are also names of other classes. Also note that we didn’t describe what the car DOES, only what it HAS. We call what it has ATTRIBUTES, and some of these attributes can also be broken down into multiple attributes. For example, there are thousands of different types and models of engines, each with distinct attributes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Car Does: Exploring Methods and Behaviors
&lt;/h2&gt;

&lt;p&gt;Now, let’s talk briefly about what a car DOES. A car:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accommodates at least one driver&lt;/li&gt;
&lt;li&gt;Can be turned on or off&lt;/li&gt;
&lt;li&gt;Moves forward or backward when the driver presses the accelerator&lt;/li&gt;
&lt;li&gt;The gear shifter changes at least whether the car moves forward or backward&lt;/li&gt;
&lt;li&gt;Changes direction to the left or right when the steering wheel is turned left or right&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just as I might have forgotten something a car DOES, there are other things I didn’t list because not every car DOES them, like sounding a warning when the horn is pressed or lighting up when the headlights are turned on. So, our class with its methods looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Attributes hidden&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    * Methods
    *
    * The internal implementation is not relevant now
    */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;acommodateDriver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Driver&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnOff&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;changeGear&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Gear&lt;/span&gt; &lt;span class="n"&gt;gear&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnLeft&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnRight&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What the car DOES, or the car’s BEHAVIOR, is called a METHOD or FUNCTION. A method or function is CALLED or INVOKED and can CALL other METHODS.&lt;/p&gt;

&lt;p&gt;Imagine everything that happens when we call the accelerate method: the accelerate method activates the engine, which, depending on the gear position, will turn gears that, in turn, rotate a shaft, which will turn the wheels in a certain direction, making the car move forward or backward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstraction and Encapsulation: Simplifying the Complex
&lt;/h2&gt;

&lt;p&gt;When stepping on the accelerator, a person doesn’t need to understand the entire vehicle’s operating mechanism, but they expect the car to move. This is called ABSTRACTION. You don’t need to know a method’s implementation, but you know the result it will produce—and when it’s not working as it should.&lt;/p&gt;

&lt;p&gt;Now imagine that to operate a car, you had to manually handle various cables, gears, and flammable fluids. Besides making the car’s operation much more complex, it would also be much more dangerous. The driver would be far more susceptible to cuts, burns, or operational errors. Instead, we simplify the process through an accelerator. The accelerator encapsulates the engine’s operation. This is called ENCAPSULATION. Encapsulation is the use of a safe and unique way to manipulate the object. Instead of handling the engine, the driver operates the accelerator.&lt;/p&gt;

&lt;p&gt;So far, we’ve introduced some concepts. If you don’t CLEARLY remember a particular concept, go back a few paragraphs, reread, research, ask an AI for an explanation, but seriously, understanding these concepts is very important. So let’s list them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Class&lt;/li&gt;
&lt;li&gt;Object or Instance&lt;/li&gt;
&lt;li&gt;Attribute&lt;/li&gt;
&lt;li&gt;Method or Function&lt;/li&gt;
&lt;li&gt;Abstraction&lt;/li&gt;
&lt;li&gt;Encapsulation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Inheritance: How F1 Cars, Pickups, and SUVs Share a Common Base
&lt;/h2&gt;

&lt;p&gt;Returning to the beginning of this post, we presented three very different cars: an F1 car, a pickup truck, and an SUV. We saw that in the basic concept common to these cars, several attributes and methods weren’t listed because not all cars have those attributes. However, we know that some cars do, and you might have wondered what to do in that case. The answer has a simple name, the one most remembered when we talk about object-oriented programming: INHERITANCE.&lt;/p&gt;

&lt;p&gt;An F1 car inherits the attributes and methods of a base car. Similarly, a pickup truck and an SUV also inherit from the base car. But let’s talk about what makes these cars unique.&lt;/p&gt;

&lt;p&gt;F1 car, among other characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accommodates only the driver&lt;/li&gt;
&lt;li&gt;Has a high-performance engine&lt;/li&gt;
&lt;li&gt;Has aerodynamic features like a spoiler and front wing&lt;/li&gt;
&lt;li&gt;Has a removable steering wheel&lt;/li&gt;
&lt;li&gt;Has no doors&lt;/li&gt;
&lt;li&gt;Has no ignition key&lt;/li&gt;
&lt;li&gt;Is lightweight&lt;/li&gt;
&lt;li&gt;Has tires and suspension for flat asphalt
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;F1&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;HighPerformanceEngine&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Airfoil&lt;/span&gt; &lt;span class="n"&gt;airfoil&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;FrontSpoiler&lt;/span&gt; &lt;span class="n"&gt;frontSpoiler&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;RemovableSteeringWheel&lt;/span&gt; &lt;span class="n"&gt;steeringWheel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;WeightReductionKit&lt;/span&gt; &lt;span class="n"&gt;weightReductionKit&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;SpeedSuspension&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;suspension&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;HighPerformanceTires&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;tires&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Java, when we use the keyword extends, we’re defining that the class inherits the attributes and methods of another class. In the case of the F1 class, it inherits from the Car class.&lt;/p&gt;

&lt;p&gt;Notice that several attributes were added, but the engine, steering wheel, and tire attributes were replaced by other classes. Thus, our F1 car will have all the attributes of a regular car, additional attributes, and different attributes.&lt;/p&gt;

&lt;p&gt;Similarly, a pickup truck, among other characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has a cargo bed&lt;/li&gt;
&lt;li&gt;Has reinforced suspension and tires suitable for carrying weight and traveling on various terrains&lt;/li&gt;
&lt;li&gt;Usually has doors&lt;/li&gt;
&lt;li&gt;Usually accommodates the driver plus 1 to 4 passengers&lt;/li&gt;
&lt;li&gt;Has headlights&lt;/li&gt;
&lt;li&gt;Has a horn
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PickupTruck&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;CargoBed&lt;/span&gt; &lt;span class="n"&gt;cargoBed&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;HeavyDutyEngine&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;HeavyDutySuspension&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;suspensions&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;AllTerrainTires&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;tires&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;Door&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;doors&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;PassengerSeat&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;passengerSeats&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;Light&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;lights&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;Horn&lt;/span&gt; &lt;span class="n"&gt;horn&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SUV, among other characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accommodates at least 3 passengers besides the driver&lt;/li&gt;
&lt;li&gt;Has tires and suspension suitable for carrying passenger weight on mostly urban and highway routes&lt;/li&gt;
&lt;li&gt;Has headlights&lt;/li&gt;
&lt;li&gt;Has a horn&lt;/li&gt;
&lt;li&gt;Has comfortable seats&lt;/li&gt;
&lt;li&gt;Has ample interior space
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SUV&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;UrbanEngine&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;UrbanSuspension&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;suspensions&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;UrbanTires&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;tires&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Door&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;doors&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;DriverComfortSeat&lt;/span&gt; &lt;span class="n"&gt;driverSeat&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;PassengerComfortSeat&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;passengerSeats&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;ComfortInternalLayout&lt;/span&gt; &lt;span class="n"&gt;comfortInternalLayout&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Light&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;lights&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Horn&lt;/span&gt; &lt;span class="n"&gt;horn&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re not convinced, look below at what the SUV class would look like if we had to reimplement all the attributes and properties of the Car class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SUV&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Chassis&lt;/span&gt; &lt;span class="n"&gt;chassis&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;UrbanEngine&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;UrbanSuspension&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;suspensions&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;UrbanTires&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;tires&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;SteeringWheel&lt;/span&gt; &lt;span class="n"&gt;steeringWheel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Door&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;doors&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;DriverComfortSeat&lt;/span&gt; &lt;span class="n"&gt;driverSeat&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;PassengerComfortSeat&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;passengerSeats&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;ComfortInternalLayout&lt;/span&gt; &lt;span class="n"&gt;comfortInternalLayout&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;GearShifter&lt;/span&gt; &lt;span class="n"&gt;gearShifter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Accelerator&lt;/span&gt; &lt;span class="n"&gt;accelerator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Brake&lt;/span&gt; &lt;span class="n"&gt;brake&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Light&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;lights&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Horn&lt;/span&gt; &lt;span class="n"&gt;horn&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accommodateDriver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Driver&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnOff&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;changeGear&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Gear&lt;/span&gt; &lt;span class="n"&gt;gear&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnLeft&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnRight&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="cm"&gt;/*
        Possibly, more specific methods.
    */&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Besides writing more code for the SUV class, we’d also have to duplicate that same code for the F1 and PickupTruck classes. In addition to code duplication, we’d also face increased difficulty in keeping this code cohesive, as we’d need the exact same code in at least three different classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Limits of Inheritance: A Glimpse at Future Challenges
&lt;/h2&gt;

&lt;p&gt;But if you’ve made it this far and are excited about using inheritance for your classes, I have some bad news for you. Take a look at the image below and tell me what you see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa16nhqq47i2aytv9yjw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa16nhqq47i2aytv9yjw6.png" alt="A bike, a speedboat and an electric car" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have a bicycle, a speedboat, and an electric car. All three are vehicles, and they all have things in common with regular cars, but they also have very distinct features. Inheritance in this case can bring excessive complexity and significant difficulty in categorizing all these objects. What can we do to solve this? That will be the topic of our next post, where we’ll continue teaching the basic concepts of object-oriented programming.&lt;/p&gt;

&lt;p&gt;Leave your comments, suggestions, and questions below. I’ll see you in the next post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted in my &lt;a href="https://blog.felipestanzani.com/2025/07/07/demystifying-object-oriented-programming-pt-1/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>A Deep Dive into JWT for Secure Web and Mobile Sessions</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Tue, 01 Jul 2025 17:25:07 +0000</pubDate>
      <link>https://dev.to/felipestanzani/a-deep-dive-into-jwt-for-secure-web-and-mobile-sessions-1c1h</link>
      <guid>https://dev.to/felipestanzani/a-deep-dive-into-jwt-for-secure-web-and-mobile-sessions-1c1h</guid>
      <description>&lt;p&gt;In the early days of electronic computing, there was no concern for privacy or security because computers were not accessible to just anyone, and even if someone had access to a computer, the chances of them knowing how to use it were negligible. Moreover, computers were not typically used to store data beyond a few dozen numbers; they were primarily used as calculators.&lt;/p&gt;

&lt;p&gt;Two decades later, even with personal computing, systems built in Clipper, Delphi, or Visual Basic ran locally or accessed databases hosted on local networks using a ring topology with coaxial cables and BNC connectors, or even on the workstation itself. The term "user session" was practically confined to academic environments and had little relevance in the real world.&lt;/p&gt;

&lt;p&gt;The real concern for data privacy and security emerged only with the popularization of the Internet, when the first applications using network communication began to appear, and the term "user session" started to gain traction among developers.&lt;/p&gt;

&lt;p&gt;Unlike applications that ran locally on the user's workstation, web applications are executed on application servers, with the frontend running in the user's browser. To maintain the user experience, the application server saves some user session information in memory or a database and sends a session ID to the user's browser, typically via cookies. This creates two problems. The first is that if a malicious person intercepts this ID, they can hijack the user's session, a process known as session hijacking. The second issue is that servers now need to allocate memory space or maintain database records to store some user information, without knowing whether the user is still actively using the application. With a small number of users, this may not be an issue, but with thousands or millions of users, things get significantly more complicated.&lt;/p&gt;

&lt;p&gt;To address the first problem, several mechanisms were created, such as CSRF tokens, session binding to the user's IP address, and others. For the second issue, stateless applications emerged. Client-side applications became more complex, leveraging JavaScript, and servers began storing minimal user session data. However, with the introduction of the iPhone, which popularized smartphones and native apps running on devices, it became necessary to find a way to maintain user sessions for these devices as well.&lt;/p&gt;

&lt;p&gt;It wouldn’t be efficient to have different methods for managing sessions across different devices, and since server-side applications had become stateless, why not apply the same principle to user sessions? This is where the JSON Web Token, more commonly known as JWT, was introduced.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Token
&lt;/h2&gt;

&lt;p&gt;JWT, defined in &lt;a href="https://datatracker.ietf.org/doc/html/rfc7519" rel="noopener noreferrer"&gt;RFC 7519&lt;/a&gt;, was created to meet the needs of web and mobile applications in a stateless, scalable way, supporting cross-domain environments like APIs and single sign-on systems. So, let’s break down how it works.&lt;/p&gt;

&lt;p&gt;A JWT is composed of three Base64-encoded JSON strings, divided into three parts separated by dots: Header.Payload.Signature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Header&lt;/strong&gt;: Contains information about the token type (JWT, in this case), the signing algorithm, and other metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload&lt;/strong&gt;: The actual token data, such as user information, permissions, token expiration date and time, and any custom data the developer wishes to include.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signature&lt;/strong&gt;: The most critical part for token security, as it ensures the token was issued by a trusted authentication server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of a Base64-encoded token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;eyJhbGciOiJIUzI&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;NiIsInR&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="err"&gt;cCI&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;IkpXVCJ&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="err"&gt;.eyJzdWIiOiIxMjM&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;NTY&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;ODkwIiwibmFtZSI&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;IkpvaG&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;gRG&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="err"&gt;lIiwiYWRtaW&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;iOnRydWUsImlhdCI&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;MTUxNjIzOTAyMn&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;.KMUFsIDTnFmyG&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;nMiGM&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;H&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="err"&gt;FNFUROf&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;wh&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="err"&gt;SmqJp-QV&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you decode this token, it will reveal the following—don’t believe me? Copy it and paste it into &lt;a href="https://jwt.io/" rel="noopener noreferrer"&gt;this site&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Header&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HS256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typ"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Payload&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1234567890"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"iat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1516239022&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each JSON object contains several keys called claims. In the payload above, for example, sub refers to the user the token was issued to. The iat claim stands for "issued at," which stores the token issuance date in Unix timestamp format as an integer. In addition to these, there are standard claims like exp and nbf, which refer to the token’s expiration date and time and the date and time from which the token becomes valid, respectively.&lt;/p&gt;

&lt;p&gt;Beyond standard claims, you can define custom claims, but use this feature cautiously to avoid exposing sensitive data, as the token’s content is not encrypted!&lt;/p&gt;

&lt;p&gt;Even though the token’s content is not encrypted, the signature ensures the token’s validity for both the client and the server. To bring a JWT into the real world, imagine a wristband used at concerts or events. After presenting your ticket, the security guard gives you a wristband based on your ticket type. Depending on the wristband’s color or design, you might access the VIP area, backstage, or only the general seating. The security guards authorizing your entry don’t need to check with anyone else about your access rights, as they can validate the wristband’s authenticity themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Are JWT Tokens Issued?
&lt;/h2&gt;

&lt;p&gt;In simple terms, issuing a JWT token is not much different from issuing a session ID, but some details completely change the dynamics of how these tokens are used. Let’s dive in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqwrd0rasjepqclchzkv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqwrd0rasjepqclchzkv.png" alt="JWT issue process" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client application sends a login request to the server.&lt;/li&gt;
&lt;li&gt;If successful, the server responds with an &lt;strong&gt;Auth Token&lt;/strong&gt; and a &lt;strong&gt;Refresh Token&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Refresh token? Yes. Applications are dynamic. A user might gain or lose access permissions, change their name, or undergo other changes. For this reason, Authentication Tokens should have a short lifespan—short enough to avoid issues if a user’s permissions change after the token is issued, but long enough to prevent the token from expiring with every request.&lt;/p&gt;

&lt;p&gt;But what happens if the token expires? That’s where the Refresh Token comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Is the Refresh Token Used?
&lt;/h2&gt;

&lt;p&gt;Unlike the Authentication Token, the Refresh Token carries minimal information beyond what’s necessary for the server to issue a new Authentication Token. Additionally, the Refresh Token has a longer lifespan.&lt;/p&gt;

&lt;p&gt;The token refresh process can be proactive or reactive. I like to combine both approaches.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4tstqskn9fw6ietjdqf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4tstqskn9fw6ietjdqf.png" alt="JWT Refresh process" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reactive Approach&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client application sends a request to the server with the Auth Token in the request header.&lt;/li&gt;
&lt;li&gt;The server verifies that the Auth Token is expired and responds with a 401 error.&lt;/li&gt;
&lt;li&gt;The client application then sends a Token Refresh request to the server with the Refresh Token in the header.&lt;/li&gt;
&lt;li&gt;The server validates the Refresh Token and responds with a new Auth Token and, optionally, a new Refresh Token, depending on how you choose to manage the user session.&lt;/li&gt;
&lt;li&gt;After receiving the new token, the client resends the initial request with the valid new token.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Proactive Approach&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client application checks that the Auth Token is expired and sends a Token Refresh request to the server with the Refresh Token in the header.&lt;/li&gt;
&lt;li&gt;The server validates the Refresh Token and responds with a new Auth Token and, optionally, a new Refresh Token, depending on how you manage the user session.&lt;/li&gt;
&lt;li&gt;After receiving the new token, the client sends the request with the valid new token.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As mentioned earlier, to avoid issues due to clock synchronization problems between the client and server, I like to send a refresh request when the Auth Token is close to expiring. However, I also maintain the reactive approach as a fallback in case the proactive method fails for any reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Is the Auth Token Used?
&lt;/h2&gt;

&lt;p&gt;There’s no mystery here: for every server request requiring authorization, the client application sends the Auth Token in the request header. If the request fails, the token refresh process is initiated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Recommendations
&lt;/h2&gt;

&lt;p&gt;As we discussed earlier, JWT token contents are not encrypted. Additionally, these tokens are susceptible to session hijacking. So, what can you do to reduce security risks with JWT? Below are 10 recommendations to improve the security of JWT-based applications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use strong signing keys (e.g., HS256, RSA) and secure storage.&lt;/li&gt;
&lt;li&gt;Validate tokens (signature, claims like exp, aud).&lt;/li&gt;
&lt;li&gt;Set short expiration times and use refresh tokens.&lt;/li&gt;
&lt;li&gt;Transmit over HTTPS only.&lt;/li&gt;
&lt;li&gt;Store tokens securely (e.g., HttpOnly cookies, not localStorage).&lt;/li&gt;
&lt;li&gt;Implement revocation (e.g., blacklists).&lt;/li&gt;
&lt;li&gt;Limit payload data, avoiding sensitive information.&lt;/li&gt;
&lt;li&gt;Protect against XSS/CSRF, replay, and algorithm downgrade attacks.&lt;/li&gt;
&lt;li&gt;Use trusted libraries and follow RFC 7519.&lt;/li&gt;
&lt;li&gt;Monitor and log token usage.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Use JWT?
&lt;/h2&gt;

&lt;p&gt;With so many security recommendations, why should you use JWT?&lt;/p&gt;

&lt;p&gt;The biggest advantage of JWT over traditional sessions is that it is stateless. Since it doesn’t rely on being stored on the application server, it saves server memory and is better suited for distributed applications across multiple domains, such as APIs, mobile apps, and more.&lt;/p&gt;

&lt;p&gt;For example, consider an application using microservices. You could have a dedicated microservice for user authentication. Other services would only need to know the authentication server’s public key to validate the user’s JWT token, without needing to query the authentication server or a database.&lt;/p&gt;

&lt;p&gt;Additionally, JWT avoids issues like CSRF, which is a concern in applications with session ID-based systems.&lt;/p&gt;

&lt;p&gt;Some frameworks, like Spring, have native support for JWT. There are also many libraries for token creation and validation. If you prefer, you can delegate authentication and authorization responsibilities to tools and services like &lt;a href="https://www.keycloak.org/" rel="noopener noreferrer"&gt;Keycloak&lt;/a&gt; (open source), &lt;a href="https://auth0.com/" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt;, &lt;a href="https://clerk.com/" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt;, and others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries for Working with JWT
&lt;/h2&gt;

&lt;p&gt;One of the most widely used libraries for JWT is &lt;strong&gt;jose&lt;/strong&gt;, which has implementations for various languages like Java, JavaScript, TypeScript, Python, and C#.&lt;/p&gt;

&lt;p&gt;Some languages have specific libraries, such as &lt;strong&gt;firebase/php-jwt&lt;/strong&gt; for PHP, &lt;strong&gt;ruby-jwt&lt;/strong&gt; for Ruby, &lt;strong&gt;golang-jwt/jwt&lt;/strong&gt; for Go, &lt;strong&gt;cpp-jwt&lt;/strong&gt; for C++, and &lt;strong&gt;SwiftJWT&lt;/strong&gt; for Swift.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://jwt.io/libraries" rel="noopener noreferrer"&gt;JWT.io&lt;/a&gt; website provides a comprehensive and detailed list of JWT libraries. Additionally, the site’s homepage offers a tool for analyzing JWT tokens, but be cautious—do not use this tool with production tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The goal of this post was not to show code but to explain the fundamental concepts of JWT. If you have a traditional website or web application with the frontend and backend in the same layer, you can continue using sessions. However, if your requirements include mobile apps, a separated frontend and backend, or distributed scenarios, JWT might be the best solution for managing your users’ sessions.&lt;/p&gt;

&lt;p&gt;If this post helped you or if you have any questions, leave them in the comments below. Until next time!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted in &lt;a href="https://blog.felipestanzani.com/2025/06/30/a-deep-dive-into-jwt-for-secure-web-and-mobile-sessions/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
      <category>security</category>
    </item>
    <item>
      <title>Life after Next.js: A New and Sunny Start</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Fri, 20 Jun 2025 19:04:55 +0000</pubDate>
      <link>https://dev.to/felipestanzani/life-after-nextjs-a-new-and-sunny-start-29n2</link>
      <guid>https://dev.to/felipestanzani/life-after-nextjs-a-new-and-sunny-start-29n2</guid>
      <description>&lt;p&gt;A few weeks ago, I posted about &lt;a href="https://blog.felipestanzani.com/2025/05/27/dont-marry-nextjs/" rel="noopener noreferrer"&gt;my decision to move away from Next.js&lt;/a&gt; and the reasons behind that choice. Since projects can't just halt, I couldn't dwell too long on my decision. I had to consider several requirements for my new stack, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using React as the frontend library.&lt;/li&gt;
&lt;li&gt;Support for Server-Side Rendering (SSR).&lt;/li&gt;
&lt;li&gt;Server-side functions.&lt;/li&gt;
&lt;li&gt;Middleware support.&lt;/li&gt;
&lt;li&gt;Enough flexibility to integrate libraries like React-Hook-Form and Axios.&lt;/li&gt;
&lt;li&gt;A caching mechanism independent of the REST library.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Initially, I was torn between &lt;em&gt;Remix&lt;/em&gt; and &lt;em&gt;TanStack Start&lt;/em&gt;. However, Remix lacks middleware support, which would necessitate significant architectural changes and a less ideal way to manage route access. Furthermore, in recent weeks, the Remix project &lt;a href="https://remix.run/blog/wake-up-remix" rel="noopener noreferrer"&gt;announced a substantial shift in direction for its V3 version&lt;/a&gt;. While this new direction appears very promising, it would eventually mean I'd have to rewrite everything again, and that's definitely not something I want.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TanStack Start&lt;/em&gt;, on the other hand, is currently in beta. Yet, it meets all my project's requirements and is built on Vite, making the project far more flexible and independent. Beyond what I've already outlined, the TanStack libraries have an excellent reputation, and this point deserves a small digression:&lt;/p&gt;

&lt;p&gt;Utah probably isn't the first place you'd pick to catch a tan, but if your name is Tanner and you have a good sense of humor, you might just call your TypeScript library stack "TanStack." This textual detour is about him: Tanner Linsley is a programmer renowned for his profound commitment to the open-source community, developer experience, and type safety. TanStack libraries are used by hundreds of thousands of developers and adopted by everyone from startups to Fortune 500 giants. This alone lends significant credibility to TanStack Start, which, at least for me, weighs heavily in my decision for a long-term project.&lt;/p&gt;

&lt;p&gt;Getting back on track, despite its beta status, the development team is now focused on stabilizing the framework rather than building new features, so no breaking changes are expected anymore.&lt;/p&gt;

&lt;p&gt;Still, you might argue that adopting a beta framework for my project carries a high risk, and I agree. However, there are other valid points to consider for my project's current stage. As I've already explained, including in the previous post, going with a no-framework approach would demand a massive effort. Staying with Next.js under Vercel's grip was out of the question. This left me with Remix, which I've already discarded, and TanStack Start, which was my choice. And here's the unexpected upside for me: working with a beta framework also has its advantages.&lt;/p&gt;

&lt;p&gt;As soon as I ran into the first development hurdles, I was directed to the &lt;a href="https://discord.gg/8vq4qJsP" rel="noopener noreferrer"&gt;TanStack Discord server&lt;/a&gt;. There, numerous developers exchange information and answer questions about the libraries. The project's own developers actively respond to queries, report bugs, ask for new issues to be opened, etc. Even Jack Herrington is there, participating actively!&lt;/p&gt;

&lt;p&gt;So what? Instead of dealing with a black box and poor documentation, I'm tracking improvements in real-time, witnessing some problems being resolved as I develop my own project, and gaining a deeper understanding of how the framework itself works.&lt;/p&gt;

&lt;p&gt;Speaking of documentation, that's another thing that genuinely surprised me. Last week, the project team removed Vinxi from the project, meaning it's now solely based on Vite, which was already planned. On the same day this version was released, all the website documentation was updated, and even a dozen example projects available on the site were already updated. These guys are truly working hard and with great dedication.&lt;/p&gt;

&lt;p&gt;If you ask me: should I transition my production project, the one paying my bills, to TanStack Start at its current stage? My recommendation is: use Angular. If you want to build almost everything from scratch, &lt;a href="https://youtu.be/TSo6pDU85dw?si=-AO1A1ck-fS3Q9zX" rel="noopener noreferrer"&gt;you can use this&lt;/a&gt;. But if you have a project that will still take a few months to be ready, and you want the opportunity to see a framework being refined in its final stages, TanStack Start will undoubtedly be an excellent choice.&lt;/p&gt;

&lt;p&gt;In my career, I've dealt with .Net 2.0, and believe me, that was far from a mature project, yet it was widely sold and adopted. The big difference is that before, I waited for Microsoft's good graces to fix the many issues – and anyone who used a MasterPage knows what I'm talking about – and now I have access to the code. If the project were to die (which I don't believe will happen), I'd have a project based on Vite and my own framework.&lt;/p&gt;

&lt;p&gt;The transition so far has been quite smooth, and the TanStack Start website itself provides &lt;a href="https://tanstack.com/start/latest/docs/framework/react/migrate-from-next-js" rel="noopener noreferrer"&gt;a very instructive guide&lt;/a&gt; for those, like me, migrating from Next.js.&lt;/p&gt;

&lt;p&gt;Regarding internationalization, unfortunately, nothing pleases me as much as &lt;code&gt;next-intl&lt;/code&gt; – for which I even &lt;a href="https://next-intl-hlpr.felipestanzani.com/" rel="noopener noreferrer"&gt;created a VSCode extension&lt;/a&gt;. To replace it, I ended up adopting &lt;code&gt;i18next&lt;/code&gt;, which comes closest, but it still lacks a canonical configuration solution or specific documentation for TanStack Start. So, Discord users have provided temporary solutions for now.&lt;/p&gt;

&lt;p&gt;Another point that greatly interests me now is replacing &lt;code&gt;react-hook-form&lt;/code&gt; with TanStack Forms, which is quite similar. I've been using &lt;a href="https://ui.shadcn.com/docs/components/form" rel="noopener noreferrer"&gt;shadcn/ui's form component&lt;/a&gt; for a while, which is based on &lt;code&gt;react-hook-form&lt;/code&gt;. I hope a new implementation based on TanStack Forms emerges and has a good level of compatibility with the current implementation. If I have enough time, I might implement this solution and make it available on GitHub.&lt;/p&gt;

&lt;p&gt;It's important to emphasize that despite being developed by the same team that builds the entire suite of TanStack libraries, one of TanStack Start's principles is that you are &lt;em&gt;not&lt;/em&gt; obliged to use any of them. It's an independent framework. Do you want to use &lt;code&gt;react-hook-form&lt;/code&gt;? Use it. Don't want to use TanStack Query? It's not even a dependency. Want to host on Vercel? Go for it. Want to put it on a Raspberry Pi hidden behind your wardrobe? Go right ahead! You are &lt;em&gt;FREE&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;More than just sharing my experience, I invite you to explore the project, participate, build your own projects based on TanStack Start, and contribute however you can.&lt;/p&gt;

&lt;p&gt;If you're also moving away from Next.js or starting a new project, what are your thoughts on TanStack Start? If you've chosen another stack, share your solution in the comments! Best regards to all!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted in my &lt;a href="https://blog.felipestanzani.com/2025/06/20/life-after-next-js-a-new-and-sunny-start/" rel="noopener noreferrer"&gt;blog, Memory Leak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Post inception</title>
      <dc:creator>Felipe Stanzani</dc:creator>
      <pubDate>Fri, 13 Jun 2025 19:12:59 +0000</pubDate>
      <link>https://dev.to/felipestanzani/post-inception-4fg2</link>
      <guid>https://dev.to/felipestanzani/post-inception-4fg2</guid>
      <description>&lt;p&gt;A friend of mine, Rogério Lino, presented WordPress to me in 2005. It was an amazing blog tool: simple, fast, and very easily customizable.&lt;/p&gt;

&lt;p&gt;20 years later, and a dozen abandoned blogs that I've forgotten, I have created my website and professional blog. When I encountered WordPress again and tried to use it for my new blog, I found a bloated tool with excessive options, unnecessary plugins, managers, etc.&lt;/p&gt;

&lt;p&gt;I tried to customize it as I wished, with a layout resembling old green-screen CRT monitors. I gave up quickly and decided to look for an alternative.&lt;/p&gt;

&lt;p&gt;A few days later, I discovered &lt;a href="https://www.11ty.dev/" rel="noopener noreferrer"&gt;11ty (Eleventy)&lt;/a&gt;. It is a static site generator that uses JavaScript, a template language of your choice for layout, and Markdown for post writing.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://blog.felipestanzani.com/2025/05/12/rethink-web-technology-html-js-css/" rel="noopener noreferrer"&gt;my post about the need for an HTML replacement&lt;/a&gt;, I wrote that XML is dying because of plenty of better options. In the same way, Markdown is by far better than HTML for writing text. It requires less code to achieve the same result. Unfortunately, I can't get rid of HTML completely yet, but for my posts, I am now free of it.&lt;/p&gt;

&lt;p&gt;I have created an awesome workflow for my posts (at least for me):&lt;/p&gt;

&lt;p&gt;I write my posts in Notion, where I can keep them, make changes, add links, leave, come back, change them again until I decide I’m done. Afterwards, I ask an LLM to review my poor English grammar—it used to be better when I was a teenager. No shame in that; it would be worse to post incorrect texts. When I finish adjusting the text, I ask an LLM to create an image to illustrate the post, and it's ready to go.&lt;/p&gt;

&lt;p&gt;Now, this is where things get really interesting. I copy the text from Notion into a Markdown file in my project along with its image. Then, I commit and push the project to the release branch on GitHub, where an Action is automatically executed. This action builds the HTML project and synchronizes the files with my hosting via FTP.&lt;/p&gt;

&lt;p&gt;11ty also generates the sitemap, robots.txt, and RSS feed XML (🤢). I really don't use SEO tools for writing: they tend to make my posts feel unnatural. If you don't the way I write, don't read; it's my memory leakage.&lt;/p&gt;

&lt;p&gt;For blog comments and reactions, I use a simple tool called Giscuss: this tool uses GitHub discussions to store these comments and reactions. You only need to configure the plugin to use a public repository discussion on GitHub. The readers must log in with their GitHub accounts to comment.&lt;/p&gt;

&lt;p&gt;You may be interested in 11ty simplicity, and I really don't need to write another tutorial teaching how to use it, since they already created &lt;a href="https://www.11ty.dev/docs/" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;, a &lt;a href="https://www.youtube.com/watch?v=kzf9A9tkkl4" rel="noopener noreferrer"&gt;6-minute video teaching how to create a blog from scratch&lt;/a&gt;, and a &lt;a href="https://github.com/11ty/eleventy-base-blog" rel="noopener noreferrer"&gt;base blog project in GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is very straightforward, and believe me: if you want to customize it, it's easier than any current WordPress tool - yes, there are many of them, and they can be totally different depending on the theme you use.&lt;/p&gt;

&lt;p&gt;If you are interested in 11ty, try it, create your blazing-fast static pages based blog, and share your experience in the comments below.&lt;/p&gt;

&lt;p&gt;Originally posted in my &lt;a href="https://blog.felipestanzani.com/2025/06/12/post-inception/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
