<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Loukmane's articles]]></title><description><![CDATA[Software Developer @MyTower. Crafting clean code by day, iced coffee addict by choice. Casual gamer and chess enjoyer ♟️💻☕. Always learning, always coding.]]></description><link>https://loukmanemaada.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1725875399325/04380d5d-867b-4d9c-a06a-7bc9d473f79b.png</url><title>Loukmane&apos;s articles</title><link>https://loukmanemaada.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 07:20:58 GMT</lastBuildDate><atom:link href="https://loukmanemaada.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How Java Virtual Threads Handles Blocking Operations Efficiently]]></title><description><![CDATA[Java’s threading model has long been a cornerstone of its concurrency capabilities. However, the limitations of traditional platform threads (wrappers around OS threads) have persisted for decades—until the release of java 21. Virtual threads, repres...]]></description><link>https://loukmanemaada.dev/how-java-virtual-threads-handles-blocking-operations-efficiently</link><guid isPermaLink="true">https://loukmanemaada.dev/how-java-virtual-threads-handles-blocking-operations-efficiently</guid><category><![CDATA[Java]]></category><category><![CDATA[Modern Java]]></category><category><![CDATA[virtualthreads]]></category><category><![CDATA[#project-loom ]]></category><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Mon, 10 Mar 2025 09:00:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/X_2IusEIKwM/upload/ec78cc03444be36fae7b3f79a35ceeca.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Java’s threading model has long been a cornerstone of its concurrency capabilities. However, the limitations of traditional platform threads (wrappers around OS threads) have persisted for decades—until the release of java 21. Virtual threads, represent a significant evolution in Java concurrency. Unlike traditional platform threads that are directly managed by the operating system (OS), virtual threads are lightweight threads handled by the Java runtime. This innovative approach dramatically improves scalability and reduces resource usage, allowing Java applications to handle numerous concurrent operations efficiently.</p>
<hr />
<h2 id="heading-the-problem-with-platform-threads"><strong>The Problem with Platform Threads</strong></h2>
<p>Traditional Java threads (platform threads) are expensive. Each thread consumes ~2MB of memory upfront and takes milliseconds to create. Operating systems limit the number of threads (often to a few thousand), making it impossible to handle millions of concurrent tasks. For I/O-heavy applications (e.g., web servers, databases), this creates a bottleneck:</p>
<ul>
<li><p><strong>CPU underutilization</strong>: A thread blocked on I/O (e.g., waiting for a database response) idles the CPU.</p>
</li>
<li><p><strong>Complex async code</strong>: To scale, developers resort to asynchronous frameworks (e.g., CompletableFuture, reactive streams), which split logic into non-blocking callbacks. While efficient, this leads to complex, hard-to-maintain code.</p>
</li>
</ul>
<hr />
<h2 id="heading-how-java-handles-blocking-operations-with-virtual-threads">How Java Handles Blocking Operations with Virtual Threads</h2>
<p>When a virtual thread encounter a blocking opertation :</p>
<ol>
<li><p><strong>Unmount</strong>: The JVM <em>unmounts</em> the virtual thread from its carrier platform thread.</p>
</li>
<li><p><strong>Yield Control</strong>: The virtual thread’s stack is moved to heap memory, freeing the platform thread to execute other tasks.</p>
</li>
<li><p><strong>Resume</strong>: Once the I/O completes, the virtual thread is rescheduled onto any available platform thread.</p>
</li>
</ol>
<p><em>But how is the yielding done ?</em><br /><em>How can the JVM know that the thread is waiting for a blocking operation ?</em></p>
<p>One word : <strong>Continuation.</strong></p>
<p>With the project Loom, all the java blocking operations are using the <strong>Continuation</strong> objects. Once a blocking operation is run, the <code>Continuation.yield()</code> is called to unmount the virtual thread, storing its execution stack in heap memory. Once the blocking operation completes, <code>Continuation.run()</code> is called, triggering the retrieving of the saved stack from the heap and remounting the virtual thread onto a platform thread, possibly a different one than before. This ensures the virtual thread resumes exactly from where it was suspended</p>
<p>The following diagram shows how java handles blocking operation (opening a file) with virtual threads</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741451783823/39a5a4f4-b53e-4d88-abb6-0d02b2e54087.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-virtual-threads-best-practices"><strong>Virtual Threads Best Practices</strong></h2>
<h3 id="heading-when-to-use-virtual-threads">When to Use Virtual Threads</h3>
<ul>
<li><p><strong>Blocking Operations:</strong> Ideal for operations involving I/O (network calls, database queries, file operations).</p>
</li>
<li><p><strong>High Concurrency:</strong> Suitable for applications requiring thousands or millions of concurrent threads due to their low resource overhead.</p>
</li>
</ul>
<h3 id="heading-when-not-to-use-virtual-threads">When Not to Use Virtual Threads</h3>
<ul>
<li><p><strong>In-Memory Computations:</strong> Avoid using virtual threads for purely CPU-bound tasks as they introduce additional overhead compared to platform threads.</p>
</li>
<li><p><strong>Native or Synchronized Blocks:</strong> Use cautiously with native calls or synchronized blocks, as virtual threads may become pinned to a platform thread, potentially reducing performance.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Java virtual threads provide a scalable and efficient approach to concurrency, particularly benefiting applications with numerous blocking operations. By effectively managing the mount, unmount, and remount lifecycle through Continuation objects, Java ensures optimal resource utilization and simpler, maintainable code. Virtual threads significantly enhance efficiency by preventing OS threads from idly waiting on I/O operations, thereby reducing overhead. Additionally, they greatly improve scalability by allowing thousands of virtual threads to be managed simultaneously without performance degradation. This model simplifies coding by enabling developers to write straightforward, synchronous code while the runtime handles concurrency intricacies seamlessly, leading to cleaner and more readable applications.</p>
]]></content:encoded></item><item><title><![CDATA[Unlocking Java's Strategy Pattern: Streamline with Lambda Expressions]]></title><description><![CDATA[Introduction
Hey there! Let's dive into design patterns—specifically, the Strategy Pattern. Once you get the hang of it, you'll start seeing it everywhere. The Strategy Pattern is all about defining a group of algorithms, wrapping each one up, and ma...]]></description><link>https://loukmanemaada.dev/unlocking-javas-strategy-pattern-streamline-with-lambda-expressions</link><guid isPermaLink="true">https://loukmanemaada.dev/unlocking-javas-strategy-pattern-streamline-with-lambda-expressions</guid><category><![CDATA[Java]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[StrategyPattern]]></category><category><![CDATA[lambda]]></category><category><![CDATA[Modern Java]]></category><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Fri, 24 Jan 2025 15:39:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Bwt5M8z1kXg/upload/a8b5edf10f8ef6f3377f3ff1507dcdcd.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Hey there! Let's dive into design patterns—specifically, the <strong>Strategy Pattern</strong>. Once you get the hang of it, you'll start seeing it everywhere. The Strategy Pattern is all about defining a group of algorithms, wrapping each one up, and making them easy to switch around. Sounds fancy, right? But honestly, traditional implementations can feel a bit... cumbersome. There's a lot of boilerplate code and extra classes just to change a behavior.</p>
<p>But here’s the good news: with modern Java and its sweet <strong>lambda expressions</strong>, we can make the Strategy Pattern lightweight, elegant, and, dare I say, fun to use.</p>
<p>Ready to see how it works? Let’s dive in!</p>
<h2 id="heading-the-problem">The Problem</h2>
<p>Alright, so picture this: you've got a service that calculates discounts. Sounds simple, right? But here's the catch—there are <em>different types</em> of discounts, and each one has its own rules. For instance:</p>
<ul>
<li><p><strong>Seasonal Discounts</strong>: Limited-time offers based on seasons or holidays.</p>
</li>
<li><p><strong>Long-Term Client Discounts</strong>: Special rewards for loyal, long-term clients.</p>
</li>
<li><p><strong>Staff Discounts</strong>: Perks for your awesome team members.</p>
</li>
<li><p><strong>Student Discounts</strong>: Discounts for the studious crowd because education deserves a break.</p>
</li>
</ul>
<p>And here's where things get tricky: each discount has its own dedicated method (see code). Now you're staring at four methods, each doing its own thing. Before you know it, you've got a service that's bloated with logic and harder to maintain than you'd like.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.stream.Collectors;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DiscountService</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Item&gt; <span class="hljs-title">applySeasonalDiscount</span><span class="hljs-params">(List&lt;Item&gt; items)</span> </span>{
        <span class="hljs-keyword">return</span> items.stream()
                .filter(Item::isDiscountable)
                .map(item -&gt; {
                    <span class="hljs-keyword">double</span> discountPercentage = <span class="hljs-number">0.1</span>;
                    discountPercentage += item.getPrice() &gt; <span class="hljs-number">500</span> ? <span class="hljs-number">0.05</span> : <span class="hljs-number">0.0</span>;
                    <span class="hljs-keyword">double</span> discountedPrice = item.getPrice() * (<span class="hljs-number">1</span> - discountPercentage);
                    <span class="hljs-keyword">return</span> item.withPrice(discountedPrice);
                })
                .collect(Collectors.toList());
    }

    <span class="hljs-comment">// Method to calculate discount for long-term clients</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Item&gt; <span class="hljs-title">applyLongTermClientDiscount</span><span class="hljs-params">(List&lt;Item&gt; items)</span> </span>{
        <span class="hljs-keyword">return</span> items.stream()
                .filter(Item::isDiscountable)
                .map(item -&gt; {
                    <span class="hljs-keyword">double</span> discountPercentage = <span class="hljs-number">0.15</span>;
                    discountPercentage += item.getPrice() &gt; <span class="hljs-number">1000</span> ? <span class="hljs-number">0.10</span> : <span class="hljs-number">0.0</span>;
                    <span class="hljs-keyword">double</span> discountedPrice = item.getPrice() * (<span class="hljs-number">1</span> - discountPercentage);
                    <span class="hljs-keyword">return</span> item.withPrice(discountedPrice);
                })
                .collect(Collectors.toList());
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Item&gt; <span class="hljs-title">applyStaffDiscount</span><span class="hljs-params">(List&lt;Item&gt; items)</span> </span>{
        <span class="hljs-keyword">return</span> items.stream()
                .filter(Item::isDiscountable)
                .map(item -&gt; {
                    <span class="hljs-keyword">double</span> discountPercentage = <span class="hljs-number">0.20</span>; 
                    <span class="hljs-keyword">double</span> discountedPrice = item.getPrice() * (<span class="hljs-number">1</span> - discountPercentage);
                    <span class="hljs-keyword">return</span> item.withPrice(discountedPrice);
                })
                .collect(Collectors.toList());
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Item&gt; <span class="hljs-title">applyStudentDiscount</span><span class="hljs-params">(List&lt;Item&gt; items)</span> </span>{
        <span class="hljs-keyword">return</span> items.stream()
                .filter(Item::isDiscountable)
                .map(item -&gt; {
                    <span class="hljs-keyword">double</span> discountPercentage = <span class="hljs-number">0.15</span>;
                    discountPercentage += item.getPrice() &lt; <span class="hljs-number">200</span> ? <span class="hljs-number">0.05</span> : <span class="hljs-number">0.0</span>;
                    <span class="hljs-keyword">double</span> discountedPrice = item.getPrice() * (<span class="hljs-number">1</span> - discountPercentage);
                    <span class="hljs-keyword">return</span> item.withPrice(discountedPrice);
                })
                .collect(Collectors.toList());
    }
}
</code></pre>
<p>Want to add a new type of discount? Get ready to add yet another method and possibly risk messing with existing ones. Not exactly the cleanest, most flexible approach, huh?</p>
<h2 id="heading-strategy-design-pattern">Strategy design pattern</h2>
<p>Using the <strong>Strategy Pattern</strong> is a fantastic way to improve the <code>DiscountService</code> class. It makes the code more flexible and organized. Each discount type can have its own strategy, which keeps the code tidy, easier to maintain, and simple to expand.</p>
<p>Here's how the code might look:</p>
<p>Let's start by defining the strategy interface:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">DiscountStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">calculateDiscountedPrice</span><span class="hljs-params">(Item item)</span></span>;
}
</code></pre>
<p>An example of the strategy implementation :</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SeasonalDiscountStrategy</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">DiscountStrategy</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">double</span> DISCOUNT_PERCENTAGE = <span class="hljs-number">0.1</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">double</span> EXPENSIVE_ITEM_DISCOUNT_PERCENTAGE = <span class="hljs-number">0.15</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">double</span> EXPENSIVE_ITEM_THRESHOLD = <span class="hljs-number">500.0</span>;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateDiscountedPrice</span><span class="hljs-params">(Item item)</span> </span>{
        <span class="hljs-keyword">double</span> discountPercentage = item.getPrice() &gt; EXPENSIVE_ITEM_THRESHOLD ? 
                                            EXPENSIVE_ITEM_DISCOUNT_PERCENTAGE 
                                            : DISCOUNT_PERCENTAGE;
        <span class="hljs-keyword">return</span> item.getPrice() * (<span class="hljs-number">1</span> - discountPercentage);
    }

}
</code></pre>
<p>The new <code>DiscountService</code> :</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.stream.Collectors;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DiscountService</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> DiscountStrategy discountStrategy;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">DiscountService</span><span class="hljs-params">(DiscountStrategy discountStrategy)</span> </span>{
        <span class="hljs-keyword">this</span>.discountStrategy = discountStrategy;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Item&gt; <span class="hljs-title">applyDiscount</span><span class="hljs-params">(List&lt;Item&gt; items)</span> </span>{
        <span class="hljs-keyword">return</span> items.stream()
                .filter(Item::isDiscountable)
                .map(item -&gt; item.withPrice(discountStrategy.calculateDiscountedPrice(item)))
                .collect(Collectors.toList());
    }
}
</code></pre>
<p>So, here's the scoop—every time you want to add a new "strategy," you need to create a brand-new class. That means setting up a class, implementing the interface, and writing what might be just a few lines of code. If you have four types of discounts, congrats—you've just made four separate classes. And don't forget: each class needs its own file, which can clutter up your project.</p>
<p>But wait, there's more. Need to tweak something? You'll be hopping between multiple files just to find the logic. Even if the logic is small, the amount of boilerplate—like method headers, constructors, and imports—makes it feel like you're doing way more work than necessary. Sure, the Strategy Pattern is awesome for complex, reusable behavior, but when your strategies are simple and focused, all that extra structure can feel like carrying a backpack full of bricks to a picnic. It's sturdy but unnecessarily heavy for the task.</p>
<h2 id="heading-the-lightweight-approach">The lightweight approach</h2>
<p>Instead of setting up a regular interface, let's go with a functional one. A functional interface is just an interface with a single abstract method.</p>
<pre><code class="lang-java"><span class="hljs-meta">@FunctionalInterface</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">DiscountStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">calculateDiscountedPrice</span><span class="hljs-params">(<span class="hljs-keyword">double</span> price)</span></span>;
}
</code></pre>
<p>In the new <code>DiscountService</code> we pass the DiscountStrategy as a prameter, aka our lambda function.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.stream.Collectors;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DiscountService</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Item&gt; <span class="hljs-title">applyDiscount</span><span class="hljs-params">(List&lt;Item&gt; items, DiscountStrategy discountStrategy)</span> </span>{
        <span class="hljs-keyword">return</span> items.stream()
                .filter(Item::isDiscountable)
                .map(item -&gt; item.withPrice(discountStrategy.calculateDiscountedPrice(item.getPrice())))
                .collect(Collectors.toList());
    }
}
</code></pre>
<p>Example of usage :</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Item&gt; items = List.of(
            <span class="hljs-keyword">new</span> Item(<span class="hljs-string">"Laptop"</span>, <span class="hljs-number">1200</span>, <span class="hljs-keyword">true</span>),
            <span class="hljs-keyword">new</span> Item(<span class="hljs-string">"Book"</span>, <span class="hljs-number">150</span>, <span class="hljs-keyword">true</span>),
            <span class="hljs-keyword">new</span> Item(<span class="hljs-string">"TV"</span>, <span class="hljs-number">600</span>, <span class="hljs-keyword">false</span>)
        );

        DiscountService discountService = <span class="hljs-keyword">new</span> DiscountService();

        List&lt;Item&gt; seasonalDiscountedItems = discountService.applyDiscount(items, 
                                             price -&gt; price * (<span class="hljs-number">1</span> - price &gt; <span class="hljs-number">500</span> ? <span class="hljs-number">0.15</span> : <span class="hljs-number">0.1</span>));
        System.out.println(<span class="hljs-string">"Seasonal Discounts: "</span> + seasonalDiscountedItems);
    }
}
</code></pre>
<p>As you can see, this approach is much more straightforward. The code clearly shows what it's doing, and adding a new discount strategy is easy. You don't need to create a new class; you can simply pass a lambda function with the logic, and the discountService will handle the calculation for you.</p>
<h2 id="heading-which-approach-to-choose"><strong>Which Approach to Choose?</strong></h2>
<ol>
<li><p><strong>Use the Traditional Strategy Pattern</strong>:</p>
<ul>
<li><p>Go for this if you expect to have complex or reusable discount logic.</p>
</li>
<li><p>It's a good fit if each strategy needs extra behavior beyond just calculating discounts.</p>
</li>
</ul>
</li>
<li><p><strong>Use Functional Interfaces and Lambdas</strong>:</p>
<ul>
<li><p>Choose this if the strategies are simple and don't need to be reused or have extra behavior.</p>
</li>
<li><p>It's great for concise, inline implementations in small-to-medium-sized projects.</p>
</li>
</ul>
</li>
</ol>
<p>Both approaches work well, and your choice should depend on how complex your project is and what it needs.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, the <strong>Strategy Pattern</strong> is a fantastic tool in software design. It gives you flexibility and makes your code easier to maintain by letting you swap out different algorithms. The traditional way of doing this can be a bit clunky with lots of extra code. But, by using Java's lambda expressions and functional interfaces, you can simplify the Strategy Pattern, making it more efficient and easier to handle. This modern method not only cuts down on code complexity but also boosts readability and adaptability, especially for projects with straightforward strategies. Whether you go with the traditional method or the lambda-based approach depends on your project's complexity and needs, but both offer great ways to handle dynamic behavior in your applications.</p>
]]></content:encoded></item><item><title><![CDATA[Mutation Testing in Java with PIT]]></title><description><![CDATA[When evaluating the quality of your tests, most developers turn to code coverage tools. These tools provide a percentage indicating how much of your code is executed by your test suite. At first glance, this seems like the ultimate metric: higher cov...]]></description><link>https://loukmanemaada.dev/mutation-testing-in-java-with-pit</link><guid isPermaLink="true">https://loukmanemaada.dev/mutation-testing-in-java-with-pit</guid><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Sun, 12 Jan 2025 17:45:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/8o_LkMpo8ug/upload/977f69fce06cdb23b03333f51cb34c39.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When evaluating the quality of your tests, most developers turn to code coverage tools. These tools provide a percentage indicating how much of your code is executed by your test suite. At first glance, this seems like the ultimate metric: higher coverage implies better-tested code, right?</p>
<p><strong>Not quite!!!</strong></p>
<p>Code coverage tells only part of the story. A test suite can hit 100% coverage and still miss critical bugs if it isn't actually validating the correctness of the code that it executes. This is where mutation testing comes in. It gives a deeper and more meaningful look at the effectiveness of your test suite by answering: Do my tests catch actual defects, or do they just run the code?</p>
<h2 id="heading-what-is-mutation-testing">What is Mutation Testing?</h2>
<p>Mutation testing is a powerful technique designed to evaluate the effectiveness of your test suite. It works by deliberately introducing small, intentional changes, or "mutations," into your source code to simulate common programming errors. These mutations might include:</p>
<ul>
<li><p>Changing a comparison operator (e.g., <code>&lt;</code> to <code>&lt;=</code>).</p>
</li>
<li><p>Replacing a boolean value (e.g., <code>true</code> to <code>false</code>).</p>
</li>
<li><p>Modifying arithmetic operations (e.g., <code>+</code> to <code>-</code>).</p>
</li>
</ul>
<p>Once mutated, your test suite is executed against this <strong>mutated</strong> code. The goal is simple: determine whether your tests can detect these <strong>defects</strong>. If the tests fail, we say the mutant is <strong>killed</strong>, indicating that the tests are robust enough to detect this defect. On the other hand if the tests pass despite running on the mutant, we say the mutant <strong>survives</strong>. A surviving mutant is an indication that there is a gap in the test coverage, the tests are not exhaustive enough to detect this subtle change of logic.</p>
<p>Now, consider a real-world scenario: during a routine refactoring, a developer inadvertently changes a <code>&lt;</code> operator to <code>&lt;=</code>. If your test suite cannot detect this defect, the bug might go unnoticed until it reaches production—where the consequences could range from subtle miscalculations to catastrophic failures. This highlights why robust tests are critical when refactoring.</p>
<p>The traditional metric of 100% code coverage, while helpful, doesn't guarantee your tests are effective. Coverage tools only measure whether your code is executed by tests, not whether your tests validate the correctness of the executed code. Mutation testing addresses this limitation by challenging your tests to prove they can identify meaningful changes in behavior. <mark>It's not enough to merely cover your code—your tests must challenge it</mark>.</p>
<h2 id="heading-example-using-pit-for-mutation-testing">Example: Using PIT for Mutation Testing</h2>
<h3 id="heading-set-up">Set up</h3>
<p>Add the PIT Maven plugin in your <code>pom.xml</code>:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.pitest<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>pitest-maven<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>LATEST<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
</code></pre>
<h3 id="heading-lets-add-some-code">Let’s add some code</h3>
<p>I created a class <code>InsurancePremiumCalculator.java</code> that calculates the amount of money the premium Insured needs to pay based on his age and type of vehicule.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InsurancePremiumCalculator</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">double</span> BASE_PREMIUM = <span class="hljs-number">500.0</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> MIN_AGE = <span class="hljs-number">16</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> MAX_AGE = <span class="hljs-number">120</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculatePremium</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age, String vehicleType)</span> </span>{
        <span class="hljs-keyword">if</span> (age &lt; MIN_AGE || age &gt; MAX_AGE) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Invalid age"</span>);
        }

        <span class="hljs-keyword">double</span> premium = BASE_PREMIUM;

        <span class="hljs-comment">// Age factor</span>
        <span class="hljs-keyword">if</span> (age &lt; <span class="hljs-number">25</span>) {
            premium *= <span class="hljs-number">1.5</span>;
        }

        <span class="hljs-comment">// Vehicle type factor</span>
        premium *= <span class="hljs-keyword">switch</span> (vehicleType.toLowerCase()) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">"sports"</span> -&gt; <span class="hljs-number">1.7</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">"suv"</span> -&gt; <span class="hljs-number">1.3</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">"sedan"</span> -&gt; <span class="hljs-number">1.0</span>;
            <span class="hljs-keyword">default</span> -&gt; <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Invalid vehicle type"</span>);
        };

        <span class="hljs-keyword">return</span> Math.round(premium * <span class="hljs-number">100.0</span>) / <span class="hljs-number">100.0</span>;
    }
}
</code></pre>
<p>Now for the test class, <code>InsurancePremiumCalculatorTest.java</code> :</p>
<pre><code class="lang-java">

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InsurancePremiumCalculatorTest</span> </span>{

    <span class="hljs-keyword">private</span> InsurancePremiumCalculator calculator;

    <span class="hljs-meta">@BeforeEach</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setUp</span><span class="hljs-params">()</span> </span>{
        calculator = <span class="hljs-keyword">new</span> InsurancePremiumCalculator();
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testBasicPremium</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">500.0</span>, calculator.calculatePremium(<span class="hljs-number">30</span>, <span class="hljs-string">"sedan"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testYoungDriverPremium</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">750.0</span>, calculator.calculatePremium(<span class="hljs-number">20</span>, <span class="hljs-string">"sedan"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testSportsCarPremium</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">850.0</span>, calculator.calculatePremium(<span class="hljs-number">30</span>, <span class="hljs-string">"sports"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testCombinedFactors</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">1275.0</span>, calculator.calculatePremium(<span class="hljs-number">22</span>, <span class="hljs-string">"sports"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testSUV</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">975.0</span>, calculator.calculatePremium(<span class="hljs-number">22</span>, <span class="hljs-string">"suv"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testInvalidAge</span><span class="hljs-params">()</span> </span>{
        assertThrows(IllegalArgumentException.class, () -&gt;
                calculator.calculatePremium(<span class="hljs-number">15</span>, <span class="hljs-string">"sedan"</span>));
        assertThrows(IllegalArgumentException.class, () -&gt;
                calculator.calculatePremium(<span class="hljs-number">121</span>, <span class="hljs-string">"sedan"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testInvalidVehicleType</span><span class="hljs-params">()</span> </span>{
        assertThrows(IllegalArgumentException.class, () -&gt;
                calculator.calculatePremium(<span class="hljs-number">30</span>, <span class="hljs-string">"invalid"</span>));
    }

}
</code></pre>
<p>Looks pretty exhaustive right ? If you shouldn’t take my word for it, let’s take a look at the tests coverage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736617066551/1803bedc-a244-42f3-b65c-500eb16af30f.png" alt class="image--center mx-auto" /></p>
<p>I have a 100% test coverage, every single line in this method is executed in one of my tests suite. Now let’s generate the mutation tests report and take a look at our PIT report.<br />We generate PIT report using the following command (assuming you have maven installed locally) :</p>
<pre><code class="lang-bash">mvn test-compile org.pitest:pitest-maven:mutationCoverage
</code></pre>
<p>You should be able to find the PIT report under<br /><code>target/pit-reports/yourpackage/index.html</code><br />Open it in your favorite browser and you should see something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736617657729/29192afb-15bf-40d4-8e07-d38c04724c7a.png" alt class="image--center mx-auto" /></p>
<p>If you click on the class name, you should find a detailed report on the class code mutations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736617807611/6bfb5cb1-8f8f-414f-923a-78a5032695f9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736617825944/bbc5ba92-093d-4353-8361-1e00cc50f1c6.png" alt class="image--center mx-auto" /></p>
<p>It seems like our tests suffers from a boundary mutation gap, which means (check PIT <a target="_blank" href="https://pitest.org/quickstart/mutators/">docs</a> for more information on mutations types) changing the &lt; or &gt; with a &lt;= and &gt;= was not detected by our tests. In other words, we have no tests that detects whetherour edge cases are respected or not. We can do that by modifying our test suite, the updated version looks something like this :</p>
<pre><code class="lang-java"> <span class="hljs-keyword">package</span> lo;

<span class="hljs-keyword">import</span> org.junit.jupiter.api.BeforeEach;
<span class="hljs-keyword">import</span> org.junit.jupiter.api.Test;

<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> org.junit.jupiter.api.Assertions.*;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InsurancePremiumCalculatorTest</span> </span>{

    <span class="hljs-keyword">private</span> InsurancePremiumCalculator calculator;

    <span class="hljs-meta">@BeforeEach</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setUp</span><span class="hljs-params">()</span> </span>{
        calculator = <span class="hljs-keyword">new</span> InsurancePremiumCalculator();
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testBasicPremium</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">500.0</span>, calculator.calculatePremium(<span class="hljs-number">30</span>, <span class="hljs-string">"sedan"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testYoungDriverPremium</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">750.0</span>, calculator.calculatePremium(<span class="hljs-number">20</span>, <span class="hljs-string">"sedan"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testSportsCarPremium</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">850.0</span>, calculator.calculatePremium(<span class="hljs-number">25</span>, <span class="hljs-string">"sports"</span>)); 
        <span class="hljs-comment">//changing 30 to 25 to test the edge case</span>
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testCombinedFactors</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">1275.0</span>, calculator.calculatePremium(<span class="hljs-number">22</span>, <span class="hljs-string">"sports"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testSUV</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">975.0</span>, calculator.calculatePremium(<span class="hljs-number">22</span>, <span class="hljs-string">"suv"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testInvalidAge</span><span class="hljs-params">()</span> </span>{
        assertThrows(IllegalArgumentException.class, () -&gt;
                calculator.calculatePremium(<span class="hljs-number">15</span>, <span class="hljs-string">"sedan"</span>));
        assertThrows(IllegalArgumentException.class, () -&gt;
                calculator.calculatePremium(<span class="hljs-number">121</span>, <span class="hljs-string">"sedan"</span>));
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testMaxAge</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">650.0</span>, calculator.calculatePremium(<span class="hljs-number">120</span>, <span class="hljs-string">"suv"</span>));
        <span class="hljs-comment">//explicitly testing the edge cases</span>
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testMinAge</span><span class="hljs-params">()</span> </span>{
        assertEquals(<span class="hljs-number">975.0</span>, calculator.calculatePremium(<span class="hljs-number">16</span>, <span class="hljs-string">"suv"</span>));
        <span class="hljs-comment">//explicitly testing the edge cases</span>
    }
    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">testInvalidVehicleType</span><span class="hljs-params">()</span> </span>{
        assertThrows(IllegalArgumentException.class, () -&gt;
                calculator.calculatePremium(<span class="hljs-number">30</span>, <span class="hljs-string">"invalid"</span>));
    }

}
</code></pre>
<p>We run the command again to generate a new report :</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736618555387/ae778283-9abc-4f22-a343-6b47ed2dd254.png" alt class="image--center mx-auto" /></p>
<p>BINGO! Our test strength is now 11/11, making our tests more reliable and better equipped to catch bugs if any changes occur.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Mutation testing is an invaluable tool for enhancing test effectiveness and ensuring code quality. By incorporating PIT into your testing strategy, you can uncover hidden weaknesses in your tests and build more robust applications.</p>
]]></content:encoded></item><item><title><![CDATA[Spring boot : A domain driven data validation]]></title><description><![CDATA[Introduction
In modern software development, data validation is important for keeping data correct and stopping incorrect input from entering a system. Spring Boot offers different ways to do data validation. However, with Java 14's new records featu...]]></description><link>https://loukmanemaada.dev/spring-boot-a-domain-driven-data-validation</link><guid isPermaLink="true">https://loukmanemaada.dev/spring-boot-a-domain-driven-data-validation</guid><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Wed, 30 Oct 2024 09:00:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/npxXWgQ33ZQ/upload/8d7db8ba0f97cf840e2aa8788171515c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In modern software development, data validation is important for keeping data correct and stopping incorrect input from entering a system. Spring Boot offers different ways to do data validation. However, with Java 14's new <strong>records</strong> feature, we can use a more design-focused way to handle data validation.</p>
<p>This article will explore how <strong>Java records</strong> can simplify and streamline the data validation process in Spring Boot. We'll adopt a design-driven mindset where each field that requires validation becomes a separate <strong>record</strong>. Through this modular approach, data becomes cleaner, validation becomes more maintainable, and the intent behind each DTO (Data Transfer Object) becomes more expressive.</p>
<h2 id="heading-why-use-records-for-dtos-in-spring-boot">Why Use Records for DTOs in Spring Boot?</h2>
<h3 id="heading-1-immutability-by-default">1. Immutability by Default</h3>
<p>Records in Java are immutable, which means their fields can't be changed once they are set. This makes them perfect for DTOs, as they usually move data between different parts of an application without needing changes. Also, I believe that user data entering the application should be kept as is and never altered!</p>
<h3 id="heading-2-concise-syntax">2. Concise Syntax</h3>
<p>With records, the boilerplate code for getters, constructors, <code>equals</code>, <code>hashCode</code>, and <code>toString</code> methods is eliminated. This helps reduce the size of DTO classes and makes them more readable and maintainable.</p>
<h3 id="heading-3-encapsulation-with-compact-constructors">3. Encapsulation with Compact Constructors</h3>
<p>The <strong>compact constructor</strong> in records allows developers to embed validation logic directly within the record's creation process. This ensures that invalid data is immediately rejected, serving as the first line of defense against faulty input. Since records lack a default constructor, the <strong>canonical constructor</strong> becomes the <strong>sole</strong> entry point for creating instances, making it the ideal place to enforce these checks.</p>
<h3 id="heading-4-aligning-with-domain-driven-design-ddd">4. Aligning with Domain-Driven Design (DDD)</h3>
<p>Using records for individual fields that require validation promotes a design-driven approach where each field becomes a <strong>self-contained component</strong>. This aligns with domain-driven design (<strong>DDD</strong>) principles by enforcing clear, domain-relevant rules directly where the data is defined.</p>
<hr />
<h2 id="heading-creating-records-as-dtos-in-spring-boot">Creating Records as DTOs in Spring Boot</h2>
<p>As mentioned before, we'll treat each field/group of fields that needs validation as its own record. This record will include not just the value but also the rules and limits for that value. We will also make use of the record’s compact constructor to add the validation logic.</p>
<p>Below is a step-by-step example to illustrate how this can be implemented.</p>
<hr />
<h3 id="heading-step-1-defining-a-record-for-field-validation">Step 1: Defining a Record for Field Validation</h3>
<p>Suppose we have a <code>User</code> DTO that contains fields such as <code>username</code>, <code>age</code>, and <code>email</code>. Each of these fields will become a separate record, containing its value and validation logic.</p>
<p>Let’s start by defining a <code>Username</code> record:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Username</span><span class="hljs-params">(<span class="hljs-meta">@JsonProperty("value")</span> String value)</span> </span>{
    <span class="hljs-keyword">public</span> Username {
        <span class="hljs-keyword">if</span>(value.isBlank()){
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Username should not be empty"</span>);
        }
    }
}
</code></pre>
<p>Here’s what’s happening:</p>
<ul>
<li><strong>Compact Constructor</strong>: Adds additional validation to enforce that the username should not be empty nor null.</li>
</ul>
<p>Similarly, let’s define an <code>Age</code> record:</p>
<pre><code class="lang-java">javaCopy codeimport jakarta.validation.constraints.Min;
<span class="hljs-keyword">import</span> jakarta.validation.constraints.Max;

<span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Age</span><span class="hljs-params">(<span class="hljs-meta">@JsonProperty("value")</span> <span class="hljs-keyword">int</span> value)</span> </span>{
    <span class="hljs-keyword">public</span> Age {
        <span class="hljs-keyword">if</span> (value &lt; <span class="hljs-number">18</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Age must be greater than 18."</span>);
        }
    }
}
</code></pre>
<p>In this example:</p>
<ul>
<li><strong>Compact Constructor</strong>: Throws an exception if the age is outside the specified range.</li>
</ul>
<p>Let’s add an <code>Email</code> record with a regex-based custom validation inside the compact constructor:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Email</span><span class="hljs-params">(<span class="hljs-meta">@JsonProperty("value")</span> String value)</span> </span>{
    <span class="hljs-keyword">public</span> Email {
        <span class="hljs-keyword">if</span> (!value.matches(<span class="hljs-string">"^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"</span>)) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Invalid email format."</span>);
        }
    }
}
</code></pre>
<p>This <code>Email</code> record ensures that the value conforms to a basic email pattern.</p>
<hr />
<h3 id="heading-step-2-combining-fields-into-a-dto-record">Step 2: Combining Fields into a DTO Record</h3>
<p>Now, let’s create a <code>User</code> record that uses these field-specific records:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">User</span><span class="hljs-params">(Username username, Age age, Email email)</span> </span>{}
</code></pre>
<p>This <code>User</code> record serves as the DTO for the entire user object, made up of individual, validated records. The benefit is that each field is validated when created, ensuring only valid data is included in the <code>User</code> record.</p>
<hr />
<h3 id="heading-step-3-using-the-dto-in-controller-classes">Step 3: Using the DTO in Controller Classes</h3>
<p>Now that we have a fully validated <code>User</code> DTO, let’s see how it can be used in a Spring Boot controller:</p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserController</span> </span>{

    <span class="hljs-meta">@PostMapping("/users")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">createUser</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> User user)</span> </span>{
        <span class="hljs-comment">// User is guaranteed to be valid at this point</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"User created successfully: "</span> + user.username().value();
    }
}
</code></pre>
<p>Here:</p>
<ul>
<li><code>@RequestBody</code>: Automatically maps the incoming JSON payload to the <code>User</code> record, triggering all field validations.</li>
</ul>
<hr />
<h2 id="heading-a-more-business-oriented-validation">A more business-oriented validation</h2>
<h3 id="heading-lets-make-our-own-spring-validator">Let’s make our own Spring validator</h3>
<p>Let's say now that the user has another business constraint: the username must be unique. It's clear that we cannot validate this at the record level since the record is a simple class and has no access to the user repository (no, we are not going to get the bean statically from the Spring context and plug it to the record class 🙂).</p>
<p>Below is a step-by-step example to illustrate how this can be implemented.</p>
<hr />
<h3 id="heading-step-1-lets-create-the-uniqueusername-annotation">Step 1: Let’s create the “UniqueUsername” annotation</h3>
<pre><code class="lang-java"><span class="hljs-meta">@Constraint(validatedBy = UniqueUsernameValidator.class)</span>
<span class="hljs-meta">@Target({ElementType.FIELD, ElementType.PARAMETER})</span>
<span class="hljs-meta">@Retention(RetentionPolicy.RUNTIME)</span>
<span class="hljs-keyword">public</span> <span class="hljs-meta">@interface</span> UniqueUsername {
    <span class="hljs-function">String <span class="hljs-title">message</span><span class="hljs-params">()</span> <span class="hljs-keyword">default</span> "Username already exists"</span>;

    Class&lt;?&gt;[] groups() <span class="hljs-keyword">default</span> {};

    Class&lt;? extends Payload&gt;[] payload() <span class="hljs-keyword">default</span> {};
}
</code></pre>
<h3 id="heading-step-2-lets-create-the-uniqueusernamevalidator-class">Step 2: Let’s create the UniqueUsernameValidator class</h3>
<p>Now let’s implement our validator. For this, we are going to be leveraging the Spring validation module (make sure you add it to your dependency manager). To do so, we are going to implement the <code>ConstraintValidator</code> interface.<br /><em><mark>NB: Each field present in this annotationwill be further discussed and explained in future articles</mark></em></p>
<pre><code class="lang-java"><span class="hljs-meta">@Component</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UniqueUsernameValidator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ConstraintValidator</span>&lt;<span class="hljs-title">UniqueUsername</span>, <span class="hljs-title">String</span>&gt; </span>{

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> UserRepository userRepository;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValid</span><span class="hljs-params">(String username, ConstraintValidatorContext context)</span> </span>{
        <span class="hljs-keyword">return</span> !userRepository.existsByUsername(username);
    }
}
</code></pre>
<h3 id="heading-step-3-update-the-existing-code">Step 3: Update the existing code</h3>
<p>Now let’s make use of our newly created validator.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Username</span><span class="hljs-params">(<span class="hljs-meta">@UniqueUsername</span> <span class="hljs-meta">@JsonProperty("value")</span> String value)</span> </span>{
    <span class="hljs-keyword">public</span> Username {
        <span class="hljs-keyword">if</span>(value.isBlank()){
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Username should not be empty"</span>);
        }
    }
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">User</span><span class="hljs-params">(<span class="hljs-meta">@Valid</span> Username username, Age age, Email email)</span> </span>{}
</code></pre>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserController</span> </span>{

    <span class="hljs-meta">@PostMapping("/users")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">createUser</span><span class="hljs-params">(<span class="hljs-meta">@Valid</span> <span class="hljs-meta">@RequestBody</span> User user)</span> </span>{
        <span class="hljs-comment">// User will be valid at this point</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"User created successfully: "</span> + user.username().value();
    }
}
</code></pre>
<p>We use <code>@Valid</code> to enable Spring validation on the object. This annotation also applies to nested objects if their fields use Spring validation, as seen with Username.<br />In summary, our objects can now validate their own state, either independently or by using Spring validation.</p>
<hr />
<h2 id="heading-benefits-of-design-driven-validation-with-records">Benefits of Design-Driven Validation with Records</h2>
<h3 id="heading-1-modular-design">1. Modular Design</h3>
<p>Each field is represented as a distinct record, encapsulating its value and validation logic. This modular design makes it easier to reuse validation logic across different DTOs.</p>
<h3 id="heading-2-early-error-detection">2. Early Error Detection</h3>
<p>Validation occurs immediately when the records are constructed, ensuring that invalid data is caught as early as possible.</p>
<h3 id="heading-3-cleaner-code">3. Cleaner Code</h3>
<p>Using records reduces the boilerplate code in your DTOs, resulting in cleaner, more maintainable code. The use of compact constructors further reduces clutter by consolidating validation logic at the point of data creation.</p>
<h3 id="heading-4-better-alignment-with-business-logic">4. Better Alignment with Business Logic</h3>
<p>By encapsulating validation logic within records, the intent behind each validation rule becomes clearer. This aligns with the principles of domain-driven design, where the code reflects the business logic and domain rules.</p>
<hr />
<h2 id="heading-drawbacks">Drawbacks</h2>
<h3 id="heading-1-potential-performance-overhead">1. Potential Performance Overhead</h3>
<p>Creating a separate record for every individual field introduces more <strong>object allocations</strong> and might impact performance.</p>
<h3 id="heading-2-reduced-readability-with-deep-nesting"><strong>2. Reduced Readability with Deep Nesting</strong></h3>
<p>If each field becomes its own record, the overall DTO can become <strong>deeply nested</strong> and harder to read. (A better way would be to use a static constructor/ builder 😋)</p>
<pre><code class="lang-java">User user = <span class="hljs-keyword">new</span> User(
    <span class="hljs-keyword">new</span> Username(<span class="hljs-string">"alice"</span>), 
    <span class="hljs-keyword">new</span> Age(<span class="hljs-number">25</span>), 
    <span class="hljs-keyword">new</span> Email(<span class="hljs-string">"alice@example.com"</span>)
);
</code></pre>
<h3 id="heading-3-less-intuitive-json-structure"><strong>3. Less intuitive json structure</strong></h3>
<p>Since each field/group of fields that need validation are record we drift away from the typical json structure to a more nested one.<br />The usual JSON we send to create a user is something like this :</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"username"</span> : <span class="hljs-string">"falcon"</span>,
    <span class="hljs-attr">"age"</span> : <span class="hljs-number">25</span>,
    <span class="hljs-attr">"email"</span> : <span class="hljs-string">"falcon@gmail.com"</span>
}
</code></pre>
<p>With this new approach, we will need to make some adjustments to the JSON.</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"Username"</span>: {
        <span class="hljs-attr">"value"</span>: <span class="hljs-string">"falcon"</span>
    },
    <span class="hljs-attr">"Age"</span>: {
        <span class="hljs-attr">"value"</span>: <span class="hljs-number">25</span>
    },
    <span class="hljs-attr">"email"</span>: {
        <span class="hljs-attr">"value"</span>: <span class="hljs-string">"falcon@gmail.com"</span>
    },
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Using records as DTOs in Spring Boot provides a design-focused method for data validation, where each field/ group of fields is a self-contained unit with its own validation rules. This not only makes validation simpler but also improves code readability and maintainability. By using the immutability and compact constructors of records, developers can ensure data integrity right from the start.</p>
<p>As software development evolves, using modern language features like records helps us write clearer, more maintainable, and error-resistant code. In a Spring Boot application, using records as DTOs for validation can result in cleaner and more reliable designs that meet both technical and business needs.</p>
]]></content:encoded></item><item><title><![CDATA[Switch expression]]></title><description><![CDATA[The introduction of switch expressions in Java marks a significant evolution in the language, overcoming several limitations of the traditional switch statement and adding new capabilities, such as pattern matching and better handling of inheritance....]]></description><link>https://loukmanemaada.dev/switch-expression-the-magic-of-modern-java</link><guid isPermaLink="true">https://loukmanemaada.dev/switch-expression-the-magic-of-modern-java</guid><category><![CDATA[Java]]></category><category><![CDATA[Modern Java]]></category><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Sun, 06 Oct 2024 17:59:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Y6O6PHJRQms/upload/aff76e0a443a3e87fef23c1f85ec29a6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The introduction of switch expressions in Java marks a significant evolution in the language, overcoming several limitations of the traditional switch statement and adding new capabilities, such as pattern matching and better handling of inheritance. This article compares the old switch statement to the new switch expression, showcases the benefits of the latter, and demonstrates how these changes can be applied to make for effective real-world scenarios concerning pattern matching and class hierarchies.</p>
<h3 id="heading-the-old-switch-statement">The Old Switch Statement</h3>
<p>In Java, the switch statement has long been a fundamental control flow structure for conditional branching. Introduced in the earliest versions of Java, it allowed developers to write code that would execute different branches based on the value of a variable, typically an integer, enum, or string in newer versions.</p>
<p>Let’s say we have an <code>int day</code> that represents the days of the week, 1 being Sunday and 7 being Saturday. We wish to print the day based on that <code>int</code>, or throw an exception if the day is invalid.</p>
<p>Using the traditional switch statement, we get something like this :</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">printDayFromInt</span><span class="hljs-params">(<span class="hljs-keyword">int</span> day)</span></span>{
String dayName;

<span class="hljs-keyword">switch</span> (day) {
    <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
        dayName = <span class="hljs-string">"Sunday"</span>;
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
        dayName = <span class="hljs-string">"Monday"</span>;
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:
        dayName = <span class="hljs-string">"Tuesday"</span>;
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:
        dayName = <span class="hljs-string">"Wednesday"</span>;
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">5</span>:
        dayName = <span class="hljs-string">"Thursday"</span>;
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">6</span>:
        dayName = <span class="hljs-string">"Friday"</span>;
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">7</span>:
        dayName = <span class="hljs-string">"Saturday"</span>;
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException();
}
System.out.println(dayName);
}
</code></pre>
<h4 id="heading-key-characteristics-of-the-old-switch">Key Characteristics of the Old Switch:</h4>
<ul>
<li><p><strong>Fall-through Behavior</strong>: Without a <code>break</code> statement at the end of each case block, the execution would fall through to the next case.</p>
</li>
<li><p><strong>Limited Return Capability</strong>: The switch statement could not directly return a value. This forces us developers to store the results in variables and handle them outside the switch block.</p>
</li>
<li><p><strong>Type Restrictions</strong>: Before Java 7, switch could only operate on primitive types (such as <code>int</code>, <code>char</code>, <code>short</code>), and Java 7 extended this to <code>String</code>. However, handling complex objects was still cumbersome.</p>
</li>
<li><p><strong>Verbosity</strong>: Multiple <code>break</code> statements and duplicated case handling led to more verbose code that was prone to errors, such as missing breaks leading to unwanted fall-through.</p>
</li>
</ul>
<h3 id="heading-2-introducing-the-new-switch-expression">2. Introducing the New Switch Expression</h3>
<p>The traditional switch statement worked well for basic control flow, but it became clumsy for more complex conditions, particularly in cases where switches needed to return values. To address these limitations, Java 12 introduced <strong>switch expressions</strong>, which were further enhanced in Java 14 and fully integrated into Java 17.</p>
<p>Switch expressions bring several benefits:</p>
<ul>
<li><p><strong>Conciseness</strong>: The <code>-&gt;</code> syntax eliminates the need for break statements.</p>
</li>
<li><p><strong>Return Values</strong>: A switch expression can return a value directly, allowing more compact code.</p>
</li>
<li><p><strong>Exhaustiveness</strong>: Switch expressions are exhaustive, meaning they must handle every possible input, either through individual cases or a <code>default</code> clause.</p>
</li>
</ul>
<p>Here’s how the same example looks using a switch expression:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">printDayFromInt</span><span class="hljs-params">(<span class="hljs-keyword">int</span> day)</span></span>{
String dayName = <span class="hljs-keyword">switch</span> (day) {
    <span class="hljs-keyword">case</span> <span class="hljs-number">1</span> -&gt; <span class="hljs-string">"Sunday"</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">2</span> -&gt; <span class="hljs-string">"Monday"</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">3</span> -&gt; <span class="hljs-string">"Tuesday"</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">4</span> -&gt; <span class="hljs-string">"Wednesday"</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">5</span> -&gt; <span class="hljs-string">"Thursday"</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">6</span> -&gt; <span class="hljs-string">"Friday"</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">7</span> -&gt; <span class="hljs-string">"Saturday"</span>;
    <span class="hljs-keyword">default</span> -&gt; <span class="hljs-string">"Invalid day"</span>;
};
System.out.println(dayName);
}
</code></pre>
<h4 id="heading-key-improvements">Key Improvements:</h4>
<ul>
<li><p><strong>No Fall-through</strong>: The <code>-&gt;</code> syntax inherently avoids fall-through, so no need for explicit <code>break</code> statements.</p>
</li>
<li><p><strong>Returning Values</strong>: Switch expressions can return a value, which simplifies code significantly. In this example, the result is directly assigned to <code>dayName</code>.</p>
</li>
<li><p><strong>Multiple Labels</strong>: Multiple cases can be combined in a single line using a comma separator.</p>
</li>
</ul>
<p>For instance:</p>
<pre><code class="lang-java">String typeOfDay = <span class="hljs-keyword">switch</span> (day) {
    <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>, <span class="hljs-number">7</span> -&gt; <span class="hljs-string">"Weekend"</span>;
    <span class="hljs-keyword">default</span> -&gt; <span class="hljs-string">"Weekday"</span>;
};
</code></pre>
<h3 id="heading-3-pattern-matching-in-switch-expressions-java-17">3. Pattern Matching in Switch Expressions (Java 17)</h3>
<p>One of the most exciting features introduced in Java 17 is <strong>pattern matching</strong> in switch expressions. This enhancement allows developers to handle different types of objects directly within a switch expression, eliminating the need for extensive <code>instanceof</code> checks and casting.</p>
<p>In earlier versions of Java, checking for object types in a class hierarchy often required nested <code>if-else</code> or switch blocks, which made the code cumbersome and harder to maintain. Pattern matching in switch provides a more elegant solution.</p>
<p>Let’s consider this scenario, I have three types of days, <code>WeekDays</code> where the <code>workHours</code> are 8 and <code>WeekEnds</code> where <code>workHours</code> are 0. Let’s create an interface <code>Days</code>, that has a single method <code>getWorkHours()</code> and let <code>WeekDays</code> and <code>WeekEnds</code> implement that interface.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Days</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">getWorkHours</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WeekDays</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Days</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getWorkHours</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">8</span>;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WeekEnds</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Days</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getWorkHours</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }
}
</code></pre>
<p>Now let’s say we want to print whether the <code>Day</code> I have passed as parameter is a weekend or a weekday.</p>
<pre><code class="lang-java">
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">printDayType</span><span class="hljs-params">(Day day)</span></span>{
    <span class="hljs-keyword">if</span>(day <span class="hljs-keyword">instanceof</span> WeekEnds){
        System.out.println(<span class="hljs-string">"WeekEnds 💃"</span>);
    }<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(day <span class="hljs-keyword">instanceof</span> WeekDays){
        System.out.println(<span class="hljs-string">"WeekDays 👨‍💻"</span>);
    }
}
</code></pre>
<p>Now, let’s use pattern matching in the switch expression to handle the different day types, but first we need to help java understand that <code>WeekDays</code> and <code>WeekEnds</code> are the only classes that inherit from the <code>Day</code> class. To do that we use the <code>permits</code>, <code>sealed</code> and <code>final</code> key words. Let’s update our code.</p>
<pre><code class="lang-java">sealed <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Days</span> <span class="hljs-title">permits</span> <span class="hljs-title">WeekDays</span>, <span class="hljs-title">WeekEnds</span></span>{
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">getWorkHours</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WeekDays</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Days</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getWorkHours</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">8</span>;
    }
}

<span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WeekEnds</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Days</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getWorkHours</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">printDayType</span><span class="hljs-params">(Day day)</span></span>{
    <span class="hljs-keyword">switch</span> (day) {
        <span class="hljs-keyword">case</span> WeekEnds weekEnds -&gt; System.out.println(<span class="hljs-string">"WeekEnds 💃"</span>);
        <span class="hljs-keyword">case</span> WeekDays weekDays -&gt; System.out.println(<span class="hljs-string">"WeekDays 👨‍💻"</span>);
    };
}
</code></pre>
<h4 id="heading-benefits-of-pattern-matching">Benefits of Pattern Matching:</h4>
<ul>
<li><p><strong>Eliminates Casting</strong>: The switch expression automatically binds the matched type to a variable (e.g., <code>WeekEnds weekEnds</code>), avoiding the need for manual casting.</p>
</li>
<li><p><strong>More Readable Code</strong>: By directly handling types within the switch, the code becomes more concise and readable.</p>
</li>
<li><p><strong>Safe and Exhaustive</strong>: Switch expressions with pattern matching enforce exhaustiveness, which means all possible cases must be handled, leading to safer and more reliable code.</p>
</li>
</ul>
<h3 id="heading-4-code-safety-first">4. Code safety first</h3>
<p>Switch expressions in Java significantly enhance code safety by enforcing exhaustiveness. Unlike traditional switch statements, where a developer could forget to handle a specific case, switch expressions ensure that all possible cases are covered. If a case is missing, the compiler will flag it, preventing the code from running until the developer addresses the issue. This compile-time safety check helps to eliminate unhandled cases and ensures that the program behaves predictably in all scenarios. By catching potential errors early, switch expressions reduce runtime bugs, making your code more robust and reliable. Additionally, they promote clearer and more maintainable code, as each branch of logic must be deliberately defined. This feature aligns with the general shift in Java towards more functional, concise, and safer code practices, reducing the risk of unintended behavior or crashes caused by unanticipated inputs.</p>
<h3 id="heading-5-conclusion">5. Conclusion</h3>
<p>The evolution from the old switch statement to the new switch expression, along with pattern matching, is a big step forward for Java. These changes make code shorter and easier to read, while also adding more safety and flexibility, especially when dealing with complex data structures and class hierarchies.</p>
<p>Switch expressions do more than just make code look nicer. They help prevent errors, make code easier to maintain, and simplify things, especially with pattern matching and polymorphism. Java developers using newer versions should adopt these changes to write cleaner and more efficient code.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding equals() and hashCode() Methods in Java and Their Role in Collections]]></title><description><![CDATA[In Java, the equals() and hashCode() methods are key for comparing objects and storing them in collections. Though they may look simple, implementing them correctly is crucial for the accuracy, performance, and reliability of Java applications, espec...]]></description><link>https://loukmanemaada.dev/understanding-equals-and-hashcode-methods-in-java-and-their-role-in-collections</link><guid isPermaLink="true">https://loukmanemaada.dev/understanding-equals-and-hashcode-methods-in-java-and-their-role-in-collections</guid><category><![CDATA[Java]]></category><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Sun, 29 Sep 2024 19:32:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/-54rPId-b9k/upload/b2f81c7763fe71eeb4158dd6f9052bb6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Java, the <code>equals()</code> and <code>hashCode()</code> methods are key for comparing objects and storing them in collections. Though they may look simple, implementing them correctly is crucial for the accuracy, performance, and reliability of Java applications, especially with collections like <code>HashSet</code>, <code>HashMap</code>, and <code>LinkedHashSet</code>.</p>
<p>This article will explore the following:</p>
<ol>
<li><p><strong>What are</strong> <code>equals()</code> and <code>hashCode()</code>?</p>
</li>
<li><p><strong>Why are they important?</strong></p>
</li>
<li><p><strong>How are they used in Java collections?</strong></p>
</li>
<li><p><strong>Best practices for overriding these methods.</strong></p>
</li>
<li><p><strong>The role of the</strong> <code>@EqualsAndHashCode</code> annotation in Lombok and how it simplifies the process.</p>
</li>
</ol>
<p>By the end, you'll understand how these methods work, how to implement them correctly, and how to use Lombok to make your Java code simpler.</p>
<h3 id="heading-1-what-are-equals-and-hashcode">1. What are <code>equals()</code> and <code>hashCode()</code>?</h3>
<h4 id="heading-the-equals-method">The <code>equals()</code> Method</h4>
<p>The <code>equals()</code> method in Java is defined in the <code>Object</code> class, which means that every Java class inherits it. Its purpose is to compare two objects for equality.</p>
<p>The default implementation of <code>equals()</code> checks for reference equality, meaning two objects are considered equal if they reference the same memory address. This is often not the desired behavior, especially when you want to compare the content of objects rather than their memory locations.</p>
<p>Here's the default implementation from the <code>Object</code> class:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">equals</span><span class="hljs-params">(Object obj)</span> </span>{
    <span class="hljs-keyword">return</span> (<span class="hljs-keyword">this</span> == obj);
}
</code></pre>
<p>In most cases, you'll want to override this method in your custom classes to compare object states (i.e., their fields).</p>
<h4 id="heading-the-hashcode-method">The <code>hashCode()</code> Method</h4>
<p>The <code>hashCode()</code> method also comes from the <code>Object</code> class. It returns an integer value (the "hash code") associated with the object. The purpose of this method is to allow objects to be efficiently stored and retrieved in hash-based collections like <code>HashMap</code> and <code>HashSet</code>.</p>
<p>The general contract of <code>hashCode()</code> is:</p>
<ul>
<li><p>If two objects are equal according to the <code>equals()</code> method, they must have the same hash code.</p>
</li>
<li><p>However, two objects having the same hash code doesn't necessarily mean they are equal.</p>
</li>
</ul>
<p>The default implementation of <code>hashCode()</code> in the <code>Object</code> class returns a unique integer based on the object's memory address:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hashCode</span><span class="hljs-params">()</span></span>;
</code></pre>
<h3 id="heading-2-why-are-equals-and-hashcode-important">2. Why Are <code>equals()</code> and <code>hashCode()</code> Important?</h3>
<p>These two methods are critical when storing objects in collections like <code>HashMap</code>, <code>HashSet</code>, or any other collection that uses hashing.</p>
<h4 id="heading-hash-based-collections-how-do-they-work">Hash-based Collections: How Do They Work?</h4>
<p>Hash-based collections, such as <code>HashMap</code> and <code>HashSet</code>, rely on <code>hashCode()</code> and <code>equals()</code> to store and retrieve objects. When an object is added to a hash-based collection, the collection uses the object's hash code to determine the "bucket" where the object should be placed. If another object is added and it has the same hash code, the collection uses <code>equals()</code> to determine whether the two objects are truly equal or if they are distinct entries.</p>
<p>Here’s a breakdown of how this works:</p>
<ol>
<li><p><strong>Storing an Object:</strong> When you store an object in a <code>HashMap</code> or <code>HashSet</code>, the collection computes the hash code of the object (via the <code>hashCode()</code> method). It then uses this value to determine the bucket in which to place the object.</p>
</li>
<li><p><strong>Retrieving an Object:</strong> When you search for an object, the collection computes the hash code of the object you're looking for and checks the appropriate bucket. If multiple objects have the same hash code, it uses <code>equals()</code> to differentiate between them.</p>
</li>
</ol>
<h4 id="heading-common-issues">Common Issues</h4>
<p>If <code>equals()</code> and <code>hashCode()</code> are not implemented correctly, you may encounter several issues:</p>
<ul>
<li><p><strong>Duplicate Entries:</strong> Objects that are logically equal may be considered different, resulting in duplicates in collections like <code>HashSet</code>.</p>
</li>
<li><p><strong>Retrieval Issues:</strong> If the hash code is not consistent with <code>equals()</code>, objects might not be retrieved correctly from collections.</p>
</li>
</ul>
<h3 id="heading-3-how-are-equals-and-hashcode-used-in-java-collections">3. How Are <code>equals()</code> and <code>hashCode()</code> Used in Java Collections?</h3>
<h4 id="heading-the-role-of-equals-and-hashcode-in-hashset">The Role of <code>equals()</code> and <code>hashCode()</code> in <code>HashSet</code></h4>
<p>A <code>HashSet</code> uses a combination of <code>hashCode()</code> and <code>equals()</code> to ensure that no two equal objects can exist in the set.</p>
<ul>
<li><p><strong>Inserting an Object:</strong> When adding an object to the <code>HashSet</code>, the collection computes the object's hash code to determine which bucket to place it in. If another object is already in that bucket, <code>equals()</code> is used to check if the two objects are equal. If they are, the new object is not added.</p>
</li>
<li><p><strong>Checking for Existence:</strong> When checking whether an object exists in a <code>HashSet</code>, the <code>hashCode()</code> of the object is computed to find the right bucket. Then, <code>equals()</code> is used to check if any object in the bucket is equal to the searched object.</p>
</li>
</ul>
<h4 id="heading-the-role-of-equals-and-hashcode-in-hashmap">The Role of <code>equals()</code> and <code>hashCode()</code> in <code>HashMap</code></h4>
<p>Similarly, <code>HashMap</code> also relies heavily on <code>equals()</code> and <code>hashCode()</code> for managing key-value pairs.</p>
<ul>
<li><p><strong>Inserting a Key-Value Pair:</strong> When a key-value pair is inserted, the hash code of the key is computed, and the key is stored in the corresponding bucket. If another key exists in that bucket, <code>equals()</code> is used to check if the keys are equal. If they are, the value is updated.</p>
</li>
<li><p><strong>Retrieving a Value:</strong> When retrieving a value by key, the hash code of the key is used to find the appropriate bucket, and <code>equals()</code> is used to locate the correct key-value pair.</p>
</li>
</ul>
<h4 id="heading-the-role-of-equals-and-hashcode-in-other-collections">The Role of <code>equals()</code> and <code>hashCode()</code> in Other Collections</h4>
<p>Collections like <code>LinkedHashSet</code>, <code>TreeSet</code>, and <code>ConcurrentHashMap</code> also rely on <code>equals()</code> and <code>hashCode()</code>, but some of them have additional ordering constraints or concurrency mechanisms.</p>
<h3 id="heading-4-best-practices-for-overriding-equals-and-hashcode">4. Best Practices for Overriding <code>equals()</code> and <code>hashCode()</code></h3>
<h4 id="heading-general-guidelines">General Guidelines</h4>
<p>When overriding <code>equals()</code> and <code>hashCode()</code>, it’s important to follow certain rules to ensure the integrity of your objects in collections.</p>
<ol>
<li><p><strong>Consistency Between</strong> <code>equals()</code> and <code>hashCode()</code>:</p>
<ul>
<li><p>If two objects are considered equal by <code>equals()</code>, they must have the same hash code.</p>
</li>
<li><p>It’s not necessary for two objects with the same hash code to be equal, but it’s a common best practice to minimize the chances of hash code collisions.</p>
</li>
</ul>
</li>
<li><p><strong>Symmetry in</strong> <code>equals()</code>:</p>
<ul>
<li>If <code>x.equals(y)</code> is <code>true</code>, then <code>y.equals(x)</code> must also be <code>true</code>.</li>
</ul>
</li>
<li><p><strong>Reflexivity in</strong> <code>equals()</code>:</p>
<ul>
<li>An object must always be equal to itself: <code>x.equals(x)</code> should always return <code>true</code>.</li>
</ul>
</li>
<li><p><strong>Transitivity in</strong> <code>equals()</code>:</p>
<ul>
<li>If <code>x.equals(y)</code> is <code>true</code> and <code>y.equals(z)</code> is <code>true</code>, then <code>x.equals(z)</code> should also be <code>true</code>.</li>
</ul>
</li>
<li><p><strong>Consistent Hash Codes:</strong></p>
<ul>
<li><p>The <code>hashCode()</code> value should be consistent as long as the object's state <mark>remains unchanged</mark>.</p>
</li>
<li><p>Avoid using mutable fields in <code>equals()</code> and <code>hashCode()</code> calculations, as changes to these fields can break collection behavior.</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-implementing-equals-and-hashcode">Implementing <code>equals()</code> and <code>hashCode()</code></h4>
<p>Here’s an example of a simple class <code>Person</code> and how to properly override <code>equals()</code> and <code>hashCode()</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">equals</span><span class="hljs-params">(Object obj)</span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span> == obj) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        }
        <span class="hljs-keyword">if</span> (obj == <span class="hljs-keyword">null</span> || getClass() != obj.getClass()) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
        }
        Person person = (Person) obj;
        <span class="hljs-keyword">return</span> age == person.age &amp;&amp; name.equals(person.name);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hashCode</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Objects.hash(name, age);
    }
}
</code></pre>
<p>In this example:</p>
<ul>
<li><p><code>equals()</code> checks both the name and age of the <code>Person</code> objects.</p>
</li>
<li><p><code>hashCode()</code> generates a hash code using <code>Objects.hash()</code>, which ensures that two equal objects will have the same hash code.</p>
</li>
</ul>
<h4 id="heading-handling-null-fields">Handling Null Fields</h4>
<p>When overriding <code>equals()</code> and <code>hashCode()</code>, always be careful with null fields. Using <code>Objects.equals()</code> in <code>equals()</code> and <code>Objects.hash()</code> in <code>hashCode()</code> helps avoid <code>NullPointerException</code>.</p>
<h3 id="heading-5-simplifying-with-lomboks-equalsandhashcode">5. Simplifying with Lombok’s <code>@EqualsAndHashCode</code></h3>
<p>Lombok is a popular Java library that helps reduce boilerplate code. It automatically generates code for common tasks like <code>getters</code>, <code>setters</code>, <code>equals()</code>, <code>hashCode()</code>, and more through annotations.</p>
<p>Lombok’s <code>@EqualsAndHashCode</code> annotation generates the <code>equals()</code> and <code>hashCode()</code> methods for you, following the best practices mentioned earlier. This is extremely useful for reducing code redundancy, especially in classes where <code>equals()</code> and <code>hashCode()</code> would otherwise be manually implemented.</p>
<p>Here’s how you can use Lombok to simplify the <code>Person</code> class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> lombok.EqualsAndHashCode;

<span class="hljs-meta">@EqualsAndHashCode</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
    }
}
</code></pre>
<p>With <code>@EqualsAndHashCode</code>, Lombok generates the <code>equals()</code> and <code>hashCode()</code> methods based on all fields of the class by default. It automatically ensures that two equal objects have the same hash code, and avoids null issues by internally using <code>Objects.equals()</code> and <code>Objects.hash()</code>.</p>
<h4 id="heading-customizing-equalsandhashcode">Customizing <code>@EqualsAndHashCode</code></h4>
<p>You can customize which fields are used for the <code>equals()</code> and <code>hashCode()</code> methods by specifying them in the annotation:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> lombok.EqualsAndHashCode;

<span class="hljs-meta">@EqualsAndHashCode(of = {"name"})</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
    }
}
</code></pre>
<p>In this example, Lombok will only use the <code>name</code> field for <code>equals()</code> and <code>hashCode()</code>, ignoring the <code>age</code> field.</p>
<p>You can also include <code>callSuper = true</code> in the annotation to include fields from the superclass in the comparison:</p>
<pre><code class="lang-java"><span class="hljs-meta">@EqualsAndHashCode(callSuper = true)</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">private</span> String employeeId;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Employee</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, String employeeId)</span> </span>{
        <span class="hljs-keyword">super</span>(name, age);
        <span class="hljs-keyword">this</span>.employeeId = employeeId;
    }
}
</code></pre>
<p>This ensures that the fields from both <code>Person</code> and <code>Employee</code> are used in <code>equals()</code> and <code>hashCode()</code>.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>The <code>equals()</code> and <code>hashCode()</code> methods are fundamental in Java for comparing objects and ensuring correct behavior in hash-based collections like <code>HashMap</code> and <code>HashSet</code>. Correctly overriding these methods is crucial for avoiding issues like duplicate objects or incorrect retrievals from collections.</p>
<p>Best practices include ensuring consistency between <code>equals()</code> and <code>hashCode()</code>, adhering to symmetry, reflexivity, and transitivity in <code>equals()</code>, and handling null values carefully. Using <code>Objects.equals()</code> and <code>Objects.hash()</code> can simplify implementation and avoid common pitfalls.</p>
<p>For developers seeking to reduce boilerplate code, Lombok’s <code>@EqualsAndHashCode</code> annotation is a powerful tool. It automatically generates <code>equals()</code> and <code>hashCode()</code> methods, allowing for customization and ensuring that your code remains clean and maintainable.</p>
<p>In conclusion, mastering <code>equals()</code> and <code>hashCode()</code> is essential for any Java developer working with collections, and tools like Lombok can greatly enhance productivity while ensuring correctness.</p>
]]></content:encoded></item><item><title><![CDATA[Deep dive into the optional java API]]></title><description><![CDATA[The Optional<T> class in Java is a container object that may or may not contain a value. Introduced in Java 8 as part of the functional programming enhancements, its goal is to provide a more expressive way to represent optional or absent values with...]]></description><link>https://loukmanemaada.dev/deep-dive-into-the-optional-java-api</link><guid isPermaLink="true">https://loukmanemaada.dev/deep-dive-into-the-optional-java-api</guid><category><![CDATA[Java]]></category><category><![CDATA[Java Programming]]></category><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Mon, 23 Sep 2024 14:25:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zlwDJoKTuA8/upload/fd8e3b510c4b658618acf4d82618aa82.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>Optional&lt;T&gt;</code> class in Java is a container object that may or may not contain a value. Introduced in Java 8 as part of the functional programming enhancements, its goal is to provide a more expressive way to represent optional or absent values without relying on null references. The <code>Optional&lt;T&gt;</code> is a fundamental class in the Java Standard Library, and it's essential for developers to understand its methods, improvements, and use cases. This article provides an exhaustive guide to the class, including its methods and how they can be used effectively in your Java code.</p>
<h2 id="heading-what-is-optional">What is optional ?</h2>
<p>At its core, <code>Optional</code> is a wrapper for a value that may or may not be present. It helps developers avoid common issues with <code>null</code>, such as <code>NullPointerException</code>, by forcing the handling of optional values.</p>
<pre><code class="lang-java">Optional&lt;String&gt; optionalValue = Optional.of(<span class="hljs-string">"Hello, Java!"</span>);
</code></pre>
<p>In this example, <code>optionalValue</code> is an <code>Optional</code> that contains a non-null value. If you pass <code>null</code> to the <code>of</code> method, it throws a <code>NullPointerException</code>. For cases where <code>null</code> is valid, you can use <code>Optional.ofNullable()</code>.</p>
<pre><code class="lang-java">Optional&lt;String&gt; optionalValue = Optional.ofNullable(<span class="hljs-keyword">null</span>);
</code></pre>
<p>With <code>Optional</code>, the intent of "this value might be absent" is explicit, and handling such cases becomes more predictable and less error-prone.</p>
<h2 id="heading-methods-in-optional">Methods in <code>Optional&lt;T&gt;</code></h2>
<p>The <code>Optional</code> class has a wide range of methods, each designed to handle optional values elegantly. Let's break down all the key methods and explore their purpose:</p>
<ol>
<li><h3 id="heading-static-factory-methods">Static Factory Methods</h3>
</li>
</ol>
<ul>
<li><p><code>empty()</code>:</p>
<blockquote>
<p>Returns an empty <code>Optional</code> instance.</p>
</blockquote>
<pre><code class="lang-java">  Optional&lt;String&gt; emptyOptional = Optional.empty();
</code></pre>
</li>
<li><p><code>of(T value)</code>:</p>
<blockquote>
<p>Returns an <code>Optional</code> with the specified non-null value.</p>
</blockquote>
<pre><code class="lang-java">  Optional&lt;String&gt; opt = Optional.of(<span class="hljs-string">"value"</span>);
</code></pre>
</li>
<li><p><code>ofNullable(T value)</code>:</p>
<blockquote>
<p>Returns an <code>Optional</code> describing the specified value, or an empty <code>Optional</code> if the value is <code>null</code>.</p>
</blockquote>
<pre><code class="lang-java">  Optional&lt;String&gt; opt = Optional.ofNullable(<span class="hljs-keyword">null</span>);
</code></pre>
</li>
</ul>
<ol start="2">
<li><h3 id="heading-basic-methods-for-value-handling">Basic Methods for Value Handling</h3>
</li>
</ol>
<ul>
<li><p><code>get()</code>:</p>
<blockquote>
<p>If a value is present, returns the value. Otherwise, throws <code>NoSuchElementException</code>.</p>
</blockquote>
</li>
<li><p><code>isPresent()</code>:</p>
<blockquote>
<p>Returns <code>true</code> if the value is present, otherwise <code>false</code>.</p>
</blockquote>
</li>
<li><p><code>isEmpty()</code> (Java 11):</p>
<blockquote>
<p>Returns <code>true</code> if the <code>Optional</code> is empty, otherwise <code>false</code>.</p>
</blockquote>
</li>
</ul>
<ol start="3">
<li><h3 id="heading-value-retrieval-with-default-handling">Value Retrieval with Default Handling</h3>
</li>
</ol>
<ul>
<li><p><code>orElse(T other)</code>:</p>
<blockquote>
<p>Returns the value if present, otherwise returns <code>other</code>.</p>
</blockquote>
</li>
<li><p><code>orElseGet(Supplier&lt;? extends T&gt; other)</code>:</p>
<blockquote>
<p>Returns the value if present, otherwise calls the <code>Supplier</code> and returns its result.</p>
</blockquote>
</li>
<li><p><code>orElseThrow()</code>:</p>
<blockquote>
<p>Returns the contained value if present, otherwise throws <code>NoSuchElementException</code>.</p>
</blockquote>
</li>
<li><p><code>orElseThrow(Supplier&lt;? extends X&gt; exceptionSupplier)</code>:</p>
<blockquote>
<p>Returns the value if present, otherwise throws an exception produced by the <code>Supplier</code>.</p>
</blockquote>
</li>
</ul>
<ol start="4">
<li><h3 id="heading-conditional-execution-methods">Conditional Execution Methods</h3>
</li>
</ol>
<ul>
<li><p><code>ifPresent(Consumer&lt;? super T&gt; action)</code>:</p>
<blockquote>
<p>If a value is present, performs the given action with the value.</p>
</blockquote>
</li>
<li><p><code>ifPresentOrElse(Consumer&lt;? super T&gt; action, Runnable emptyAction)</code> (Java 9):</p>
<blockquote>
<p>If a value is present, performs the action with the value; otherwise, runs the <code>emptyAction</code>.</p>
</blockquote>
</li>
</ul>
<ol start="5">
<li><h3 id="heading-mapping-methods">Mapping Methods</h3>
</li>
</ol>
<ul>
<li><p><code>map(Function&lt;? super T, ? extends U&gt; mapper)</code>:</p>
<blockquote>
<p>If a value is present, applies the provided mapping function to it and returns a new <code>Optional</code> with the result.</p>
</blockquote>
</li>
<li><p><code>flatMap(Function&lt;? super T, Optional&lt;U&gt;&gt; mapper)</code>:</p>
<blockquote>
<p>Similar to <code>map()</code>, but the mapper function must return an <code>Optional</code>.</p>
</blockquote>
</li>
<li><p><code>filter(Predicate&lt;? super T&gt; predicate)</code>:</p>
<blockquote>
<p>If a value is present and it matches the given predicate, returns an <code>Optional</code> describing the value; otherwise, returns an empty <code>Optional</code>.</p>
</blockquote>
</li>
</ul>
<ol start="6">
<li><h3 id="heading-stream-and-iteration">Stream and Iteration</h3>
</li>
</ol>
<ul>
<li><p><code>stream()</code> (Java 9):</p>
<blockquote>
<p>If a value is present, returns a <code>Stream</code> containing the value; otherwise, returns an empty <code>Stream</code>.</p>
</blockquote>
</li>
</ul>
<h2 id="heading-best-practices-for-using-optional">Best Practices for Using <code>Optional</code></h2>
<ul>
<li><p><strong>Avoid using</strong> <code>Optional</code> for fields/parameters: <code>Optional</code> was designed for return types and not as a type for class members or arguments for methods. Using <code>Optional</code> in fields/parameters can lead to unnecessary complications.</p>
</li>
<li><p><strong>Use</strong> <code>Optional</code> for method return types: It's an excellent choice for methods that might return <code>null</code>. It forces the caller to handle the absent case explicitly.</p>
</li>
<li><p><strong><mark>Do not use</mark></strong> <code>Optional.get()</code>: I can't stress this enough, but this method defeats the purpose of using <code>Optional</code>, as it reintroduces the risk of <code>NoSuchElementException</code>. Prefer safer alternatives like <code>orElse()</code>, <code>orElseThrow()</code>, or <code>ifPresent()</code>.</p>
</li>
<li><p><strong>Use</strong> <code>ifPresentOrElse()</code> for clear fallback logic: This method is particularly useful when you need to handle both the presence and absence of a value with different actions.</p>
</li>
</ul>
<h2 id="heading-clean-code-example-with-optional">Clean code example with Optional</h2>
<ol>
<li><h3 id="heading-no-null-check">No null check</h3>
</li>
</ol>
<p>The following code get the name of a user using his id, if the user is not found we return null.<br />Old way of doing this :</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getNameById</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{
    User user = findUserById(id);
    <span class="hljs-keyword">if</span>(user == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
    <span class="hljs-keyword">return</span> user.getName();
}
</code></pre>
<p>Using <code>Optional</code>, we can see clearly from the method signature that the result might be absent. The code is more expressive, and the use of <code>map()</code> eliminates explicit <code>null</code> checks, making it more readable.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> Optional&lt;String&gt; <span class="hljs-title">getNameById</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{
    <span class="hljs-keyword">return</span> Optional.ofNullable(findUserById(id))
                   .map(User::getName);
}
</code></pre>
<ol start="2">
<li><h3 id="heading-chain-methods-not-ifs">Chain methods not ifs</h3>
<p> The following code gets the company name from the user entity. It gets the adress then the company then the company name. If a null is found it returns <em>“unknown”</em>.</p>
</li>
</ol>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getCompanyName</span><span class="hljs-params">(User user)</span> </span>{
    <span class="hljs-keyword">if</span> (user != <span class="hljs-keyword">null</span>) {
        Address address = user.getAddress();
        <span class="hljs-keyword">if</span> (address != <span class="hljs-keyword">null</span>) {
            Company company = address.getCompany();
            <span class="hljs-keyword">if</span> (company != <span class="hljs-keyword">null</span>) {
                <span class="hljs-keyword">return</span> company.getName();
            }
        }
    }
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Unknown"</span>;
}
</code></pre>
<p><code>Optional</code> does a magnificent job in making this kind of use cases simple.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getCompanyName</span><span class="hljs-params">(User user)</span> </span>{
    <span class="hljs-keyword">return</span> Optional.ofNullable(user)
                   .map(User::getAddress)
                   .map(Address::getCompany)
                   .map(Company::getName)
                   .orElse(<span class="hljs-string">"Unknown"</span>);
}
</code></pre>
<p>By using the <code>Optional</code> API we avoided using multiple if statments.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The <code>Optional&lt;T&gt;</code> class provides a powerful and expressive way to handle potential absence of values in Java. Its methods are designed to encourage a functional programming style, reducing the need for <code>null</code> checks and making your code cleaner and safer. With its rich API, you can handle optional values in multiple ways, each designed to fit specific use cases.</p>
<p>Understanding how to effectively use <code>Optional</code> can drastically improve the readability and reliability of your Java applications. Whether you're working with legacy code or developing new systems, integrating <code>Optional</code> in return types helps signal the possibility of missing values in a clear and type-safe way.</p>
]]></content:encoded></item><item><title><![CDATA[Records in java :  the illusion of immutability]]></title><description><![CDATA[Java records, as I mentioned in my last article, offer a new way to define classes that hold immutable data. Records make it easier to create data carriers with fixed states at creation. However, this immutability can be misleading when records have ...]]></description><link>https://loukmanemaada.dev/records-in-java-the-illusion-of-immutability</link><guid isPermaLink="true">https://loukmanemaada.dev/records-in-java-the-illusion-of-immutability</guid><category><![CDATA[Java]]></category><category><![CDATA[Java Programming]]></category><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Thu, 12 Sep 2024 11:45:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/WTeucliaDfQ/upload/01cfa441988456aabcc210964c2840f0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Java records, as I mentioned in my last <a target="_blank" href="https://loukmanemaada.hashnode.dev/records-an-elegant-way-to-transfer-data-in-java">article</a>, offer a new way to define classes that hold immutable data. Records make it easier to create data carriers with fixed states at creation. However, this immutability can be misleading when records have fields with mutable objects.</p>
<p>While you can't reassign the record's fields, the objects they reference, like mutable collections, can still be modified. This creates an illusion of immutability—where the record's structure looks immutable, but its contents <mark>can still change</mark>, going against the main idea of immutability that records aim to promote.</p>
<p>In this article, we'll look at why Java records might not be as immutable as they seem, especially with mutable collections, and discuss ways to handle this issue.</p>
<h2 id="heading-understanding-java-records-a-quick-recap"><strong>Understanding Java Records: A Quick Recap</strong></h2>
<p>At its core, a record is a special kind of class in Java:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">User</span><span class="hljs-params">(String name)</span> </span>{}
</code></pre>
<p>This <code>User</code> record automatically generates the following:</p>
<ul>
<li><p>A constructor to initialize the field <code>name</code>.</p>
</li>
<li><p>Accessor method <code>name()</code>.</p>
</li>
<li><p><code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> methods.</p>
</li>
</ul>
<p>You might think that since the fields are <code>final</code>, the object is fully immutable. However, immutability only applies to <mark> the references </mark> stored in those fields, not to the objects they point to.</p>
<h2 id="heading-the-problem-mutable-objects"><strong>The Problem: Mutable Objects</strong></h2>
<p>Let’s extend our <code>User</code> example to include a <code>List&lt;String&gt;</code> to store phone numbers:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">User</span><span class="hljs-params">(String name, List&lt;String&gt; phoneNumbers)</span> </span>{}
</code></pre>
<p>On the surface, this seems immutable because we can’t reassign <code>phoneNumbers</code> to a different list. But the real problem lies in the fact that <code>List&lt;String&gt;</code> itself is mutable/immutable depending on the implementation we choose to use, for demonstration purpuses, we will be using the <code>ArrayList</code> (a mutable collection) implementation:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;String&gt; phoneNumbers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        phoneNumbers.add(<span class="hljs-string">"+33 613-56-91-91"</span>);

        <span class="hljs-keyword">var</span> user = <span class="hljs-keyword">new</span> User(<span class="hljs-string">"John"</span>, phoneNumbers);
        System.out.println(person.phoneNumbers()); <span class="hljs-comment">// [+33 613-56-91-91]</span>

        <span class="hljs-comment">// Mutating the list from outside the </span>
        user.phoneNumbers().add(<span class="hljs-string">"+33 615-25-40-49"</span>);
        System.out.println(user.phoneNumbers()); <span class="hljs-comment">// [+33 613-56-91-91, +33 615-25-40-49]</span>
    }
}
</code></pre>
<p>The record guarantees that the reference to <code>phoneNumbers</code> is immutable, but the contents of the list can still be changed. This breaks the illusion of immutability, as the <code>User</code> object can be modified indirectly.</p>
<p>To illustrate the immutability of the reference, let’s take a look at this code :</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;String&gt; phoneNumbers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        phoneNumbers.add(<span class="hljs-string">"+33 613-56-91-91"</span>);

        <span class="hljs-keyword">var</span> user = <span class="hljs-keyword">new</span> User(<span class="hljs-string">"John"</span>, phoneNumbers);

        <span class="hljs-comment">// error: cannot assign a value to final variable phoneNumbers</span>
        user.phoneNumbers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(user.phoneNumbers());
    }
</code></pre>
<h3 id="heading-why-does-this-happen"><strong>Why Does This Happen?</strong></h3>
<p>Java’s immutability for records only applies to fields themselves, not to the objects those fields reference. Since <code>List</code> is mutable, we can modify its contents even though the reference itself is final. This applies to <mark>any mutable Object</mark>.</p>
<p>The mutability issue arises because collections in Java, by default, do not enforce immutability. While you can't reassign a new list to <code>phoneNumbers</code> in the <code>User</code> record, you can modify the list itself.</p>
<h2 id="heading-alternatives-enforcing-immutability"><strong>Alternatives: Enforcing Immutability</strong></h2>
<p>To preserve true immutability with mutable Collections inside a record, you have a few options:</p>
<h3 id="heading-1-defensive-copying"><strong>1. Defensive Copying</strong></h3>
<p>One common approach is to make a defensive copy of the collection during record initialization. This ensures that even if the original collection is mutable, the copy stored in the record is isolated from external modifications. This can be achieved by adding the following code to the canonical constructor of the <code>User</code> record.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Collections;

<span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">User</span><span class="hljs-params">(String name, List&lt;String&gt; phoneNumbers)</span> </span>{
    <span class="hljs-keyword">public</span> User{
        <span class="hljs-comment">// Defensive copy</span>
        phoneNumbers = List.copyOf(phoneNumbers);
    }
}
</code></pre>
<p>In this example, <code>List.copyOf(addresses)</code> creates an unmodifiable copy of the input list. Any attempts to modify this copy will result in <code>UnsupportedOperationException</code>.</p>
<h3 id="heading-2-using-unmodifiable-collections"><strong>2. Using Unmodifiable Collections</strong></h3>
<p>If you’re dealing with a collection that should never be modified, you can use Java's unmodifiable collections:</p>
<pre><code class="lang-java">javaCopy codeimport java.util.List;
<span class="hljs-keyword">import</span> java.util.Collections;

<span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, List&lt;String&gt; addresses)</span> </span>{
    <span class="hljs-keyword">public</span> Person {
        <span class="hljs-comment">// Wrapping the list as unmodifiable</span>
        addresses = Collections.unmodifiableList(<span class="hljs-keyword">new</span> ArrayList&lt;&gt;(addresses));
    }
}
</code></pre>
<p>Here, <code>Collections.unmodifiableList()</code> returns a read-only view of the list. While you can still pass a mutable list into the record, the record itself will only expose an unmodifiable version, preventing external changes.</p>
<h3 id="heading-3-generic-alternative"><strong>3. Generic alternative :</strong></h3>
<p>If you need to maintain mutability outside of the record—meaning that the objects returned by the getters are still mutable but cannot affect the record’s internal state—you can achieve this by making defensive copies both during the record's initialization and in the getter method. This approach ensures that any mutations performed on the returned object don't affect the record’s internal data. Let’s look at the updated <code>User</code> record code :</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">User</span><span class="hljs-params">(String name, List&lt;String&gt; phoneNumbers)</span> </span>{

    <span class="hljs-comment">// Defensive copy in the constructor</span>
    <span class="hljs-keyword">public</span> User {
        <span class="hljs-comment">// Create a defensive copy to prevent external modifications</span>
        addresses = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(addresses);
    }

    <span class="hljs-comment">// Defensive copy in the getter</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;String&gt; <span class="hljs-title">addresses</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Return a mutable copy of the addresses</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(addresses);
    }
}
</code></pre>
<p>Now let’s run our code :</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;String&gt; phoneNumbers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        phoneNumbers.add(<span class="hljs-string">"+33 613-56-91-91"</span>);

        <span class="hljs-keyword">var</span> user = <span class="hljs-keyword">new</span> User(<span class="hljs-string">"John"</span>, phoneNumbers);
        System.out.println(person.phoneNumbers()); <span class="hljs-comment">// [+33 613-56-91-91]</span>

        <span class="hljs-comment">// Mutating the list from outside the record</span>
        user.phoneNumbers().add(<span class="hljs-string">"+33 615-25-40-49"</span>);
        System.out.println(user.phoneNumbers()); <span class="hljs-comment">// [+33 613-56-91-91]</span>
    }
}
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>While Java records are designed to simplify the creation of immutable data classes, the immutability they promise can be misleading when dealing with mutable objects. Since objects like <code>ArrayList</code> remain mutable, they can undermine the immutability of records.</p>
<p>To address this, you can adopt several strategies:</p>
<ul>
<li><p>Defensive copying.</p>
</li>
<li><p>Using unmodifiable collections provided by Java’s <code>Collections</code> utility class (Collection specific sollution).</p>
</li>
<li><p>Returning a copy of the object.</p>
</li>
</ul>
<p>By incorporating these approaches, you can ensure that your Java records live up to the promise of immutability, even when mutable Objects are involved.</p>
]]></content:encoded></item><item><title><![CDATA[Records: An Elegant Way to Transfer Data in Java]]></title><description><![CDATA[With the introduction of Java 14, one of the most prominent features was "Records." Records offer a new approach to modeling classes as bearers of immutable data. Traditionally, building a basic data transfer object (DTO) in Java required a lot of bo...]]></description><link>https://loukmanemaada.dev/records-an-elegant-way-to-transfer-data-in-java</link><guid isPermaLink="true">https://loukmanemaada.dev/records-an-elegant-way-to-transfer-data-in-java</guid><dc:creator><![CDATA[MAADA Loukmane]]></dc:creator><pubDate>Thu, 05 Sep 2024 13:50:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/T3mKJXfdims/upload/516316784f58e6b5cb8ed34cd9fae97f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With the introduction of Java 14, one of the most prominent features was "Records." Records offer a new approach to modeling classes as bearers of immutable data. Traditionally, building a basic data transfer object (DTO) in Java required a lot of boilerplate code. Records considerably decrease this burden and provide an intuitive way to encapsulate and transport data.</p>
<p>In this article, we will explore what Records are, how they work, why to use them, and most importantly, when to use them.</p>
<h3 id="heading-what-are-java-records">What are Java Records?</h3>
<p>Records are a special kind of classes designed mainly to hold immutable data. It automatically generate the necessary methods for basic data handling, which helps reduces the amount of boiler plate commonly associated with plain java objects, such as constructors, getters, <code>toString()</code>, <code>hashCode()</code>, and <code>equals()</code> methods. By default Records in java are immutable, once created the data it holds cannot be changed.</p>
<h3 id="heading-syntax">Syntax</h3>
<p>Let's create a Book class in the traditional Java way. Our class Book should have a title, a price, an ISBN and finally the authors name.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.Objects;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String title;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">double</span> price;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String isbn;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String authorName;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Book</span><span class="hljs-params">(String title, <span class="hljs-keyword">double</span> price, String isbn, String authorName)</span> </span>{
        <span class="hljs-keyword">this</span>.title = title;
        <span class="hljs-keyword">this</span>.price = price;
        <span class="hljs-keyword">this</span>.isbn = isbn;
        <span class="hljs-keyword">this</span>.authorName = authorName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getTitle</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> title;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getPrice</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> price;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getIsbn</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> isbn;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getAuthorName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> authorName;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">equals</span><span class="hljs-params">(Object o)</span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span> == o) <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        <span class="hljs-keyword">if</span> (o == <span class="hljs-keyword">null</span> || getClass() != o.getClass()) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
        Book book = (Book) o;
        <span class="hljs-keyword">return</span> Double.compare(book.price, price) == <span class="hljs-number">0</span> &amp;&amp;
                title.equals(book.title) &amp;&amp;
                isbn.equals(book.isbn) &amp;&amp;
                authorName.equals(book.authorName);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hashCode</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Objects.hash(title, price, isbn, authorName);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Book{"</span> +
                <span class="hljs-string">"title='"</span> + title + <span class="hljs-string">'\''</span> +
                <span class="hljs-string">", price="</span> + price +
                <span class="hljs-string">", isbn='"</span> + isbn + <span class="hljs-string">'\''</span> +
                <span class="hljs-string">", authorName='"</span> + authorName + <span class="hljs-string">'\''</span> +
                <span class="hljs-string">'}'</span>;
    }
}
</code></pre>
<p>Phew ! that's a lot of code lines for such a simple class.</p>
<p><strong>NB</strong>: We use the <code>final</code> keyword in this example to ensure the immutablity.</p>
<p>Let's try to do the same but this time with records</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Book</span><span class="hljs-params">(String title, <span class="hljs-keyword">double</span> price, String isbn, String authorName)</span> </span>{}
</code></pre>
<p>And yes, it's as simple as that. Java will handle generating the constructor, the getters, the hash, equals, and toString methods. No setters are needed because records are immutable.</p>
<h3 id="heading-why-use-records">Why Use Records?</h3>
<ul>
<li><p><strong>Immutability by Design :</strong> Records are immutable, which makes them ideal for thread safe data transfer.</p>
</li>
<li><p><strong>Reduced Boilerplate Code:</strong> Records automatically generate the data handling methods, drastically reducing the boilerplate code, making the classes easier to maintain and read.</p>
</li>
</ul>
<h3 id="heading-some-use-cases">Some use cases</h3>
<ul>
<li><p><strong>Data Transfer Objects(DTOs) :</strong> DTOs are simple objects that move data between different parts of an application, like in REST APIs, service layers, or database queries. Records are great for this because of their built in immutability.</p>
</li>
<li><p><strong>Return Types for Methods:</strong> Record can be used to bundle values from multiple related data source.This eliminates the need for verbose classes or cumbersome return types like <strong><em>maps</em></strong> or <strong><em>arrays</em></strong>.</p>
</li>
</ul>
<h3 id="heading-records-and-data-validation">Records and data validation</h3>
<p>Although Records automatically generate constructors and methods, you can still customize their behavior if needed. For example, you can define additional methods inside a Record or provide custom validation logic.</p>
<p>For example, a Book cannot have a negative price. Fortunately, Java has thought of this and introduced the canonical constructor.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">Book</span><span class="hljs-params">(String title, <span class="hljs-keyword">double</span> price, String isbn, String authorName)</span> </span>{

    <span class="hljs-comment">// Canonical constructor</span>
    <span class="hljs-keyword">public</span> Book {
        <span class="hljs-keyword">if</span> (price &lt; <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Price cannot be negative"</span>);
        }
    }
}
</code></pre>
<p>If we take a look at the generated code, the <code>Book.class</code> file we'll find this constructor.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Book</span><span class="hljs-params">(String title, <span class="hljs-keyword">double</span> price, String isbn, String authorName)</span> </span>{
            <span class="hljs-keyword">if</span> (price &lt; <span class="hljs-number">0.0</span>) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Price cannot be negative"</span>);
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">this</span>.title = title;
                <span class="hljs-keyword">this</span>.price = price;
                <span class="hljs-keyword">this</span>.isbn = isbn;
                <span class="hljs-keyword">this</span>.authorName = authorName;
            }
        }
</code></pre>
<p>The code we put in the canonical constructor was inserted into the generated constructor.</p>
<h3 id="heading-limitations">Limitations</h3>
<p>While Records are useful, they are not suitable for all situations and have some limitations :</p>
<ul>
<li><p><strong>Immutability :</strong> Records cannot be used if you need mutable data structures like a database entity. In that case a traditional java class would be more appropriate</p>
</li>
<li><p><strong>No Inheritance:</strong> Records can implement interfaces; however, they cannot extend other classes because they already extend the Record class. We can see that if we inspect the bytecode using the <code>javap -c</code> command.</p>
<pre><code class="lang-java">  <span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">java</span>.<span class="hljs-title">lang</span>.<span class="hljs-title">Record</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> java.lang.String title;
  <span class="hljs-comment">// the rest is hidden</span>
</code></pre>
</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Java Records offer a simple and modern way to handle data by reducing boilerplate code, ensuring immutability, and making code easier to read. They come with built-in <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> methods, making them great for data transfer objects, method return types, and configuration classes.</p>
<p>Although they have some limitations, their ease of use and power make them a useful tool for Java developers. As Java evolves, Records will likely become a common pattern for managing simple, unchangeable data structures, helping us developers write cleaner and more maintainable code.</p>
]]></content:encoded></item></channel></rss>