<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ashutosh Krishna</title>
    <description>The latest articles on DEV Community by Ashutosh Krishna (@ashutoshkrris).</description>
    <link>https://dev.to/ashutoshkrris</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F423814%2Fda52356e-128f-4061-a8c6-31b056541ae7.png</url>
      <title>DEV Community: Ashutosh Krishna</title>
      <link>https://dev.to/ashutoshkrris</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashutoshkrris"/>
    <language>en</language>
    <item>
      <title>The Ultimate Guide to the Java Singleton Pattern</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Sun, 12 Jul 2026 09:28:23 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/the-ultimate-guide-to-the-java-singleton-pattern-1oe0</link>
      <guid>https://dev.to/ashutoshkrris/the-ultimate-guide-to-the-java-singleton-pattern-1oe0</guid>
      <description>&lt;p&gt;Imagine a country. A country can have millions of citizens, thousands of politicians, and hundreds of cities, but it only ever has &lt;strong&gt;one President&lt;/strong&gt; at a time. Whenever a citizen, a foreign diplomat, or a journalist wants to address the head of state, they all route their communication to that exact same person.&lt;/p&gt;

&lt;p&gt;In software engineering, there are certain objects in our systems that must operate exactly like this President. We need exactly &lt;em&gt;one&lt;/em&gt; instance of them, and we need a global point of access to reach them.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;Singleton Design Pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Singleton is one of the “Gang of Four” (GoF) creational design patterns. It is arguably the most famous design pattern in existence and simultaneously one of the most controversial. Whether you are building a configuration manager, a printer spooler, or a centralised logger, Singleton ensures that all parts of your application share the same state and resources.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Interview Tip:&lt;/strong&gt; Interviewers love asking about Singletons because it is a “gateway pattern”. A simple question about Singleton quickly opens the door to complex discussions about multi-threading, the Java Memory Model, class loaders, and reflection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
What is a Singleton Class?

&lt;ul&gt;
&lt;li&gt;Key Characteristics&lt;/li&gt;
&lt;li&gt;Benefits&lt;/li&gt;
&lt;li&gt;Drawbacks&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Why Do We Need Singleton?&lt;/li&gt;
&lt;li&gt;Core Principles Behind Singleton&lt;/li&gt;
&lt;li&gt;
Basic Singleton Implementation: Eager Initialization

&lt;ul&gt;
&lt;li&gt;The Problem&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Lazy Initialization: Saving Memory

&lt;ul&gt;
&lt;li&gt;The Problem&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Synchronized Method: The Traffic Jam

&lt;ul&gt;
&lt;li&gt;The Problem&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Double-Checked Locking&lt;/li&gt;
&lt;li&gt;Understanding the &lt;code&gt;volatile&lt;/code&gt; Keyword&lt;/li&gt;
&lt;li&gt;The Bill Pugh Singleton: A JVM Masterclass&lt;/li&gt;
&lt;li&gt;The Reflection Problem&lt;/li&gt;
&lt;li&gt;The Serialization Problem&lt;/li&gt;
&lt;li&gt;The Cloning Problem&lt;/li&gt;
&lt;li&gt;The Enum Singleton: The Indestructible Solution&lt;/li&gt;
&lt;li&gt;Singleton and Class Loaders: An Enterprise Reality&lt;/li&gt;
&lt;li&gt;Comparing All Singleton Implementations&lt;/li&gt;
&lt;li&gt;Singleton vs Static Utility Class&lt;/li&gt;
&lt;li&gt;Singleton in the Spring Framework&lt;/li&gt;
&lt;li&gt;Singleton in Modern Cloud Applications&lt;/li&gt;
&lt;li&gt;When NOT to Use Singleton (The Anti-Pattern Debate)&lt;/li&gt;
&lt;li&gt;Common Mistakes Developers Make&lt;/li&gt;
&lt;li&gt;Best Practices for Modern Development&lt;/li&gt;
&lt;li&gt;Common Interview Questions and Answers&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a Singleton Class?
&lt;/h2&gt;

&lt;p&gt;By formal definition, the Singleton pattern ensures that a class has &lt;strong&gt;only one instance&lt;/strong&gt; and provides a &lt;strong&gt;global point of access&lt;/strong&gt; to that instance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Characteristics
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One Instance:&lt;/strong&gt; The JVM will only ever contain one object of this class per classloader.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-Managed:&lt;/strong&gt; The class itself is responsible for keeping track of its sole instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global Access:&lt;/strong&gt; The class provides a public static method to allow clients to retrieve the instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Benefits&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Prevents other objects from instantiating their own copies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conserves memory by sharing a single object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Centralises the state and management of a shared resource.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Drawbacks&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Introduces global state into an application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tightly couples code, making unit testing difficult.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can cause hidden bottlenecks in heavily multi-threaded environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Do We Need Singleton?
&lt;/h2&gt;

&lt;p&gt;Why not just create new objects every time we need them using the &lt;code&gt;new&lt;/code&gt; keyword?&lt;/p&gt;

&lt;p&gt;Creating objects in Java has a cost: memory allocation, CPU cycles, and Garbage Collection overhead. But more importantly, some objects represent resources that are strictly singular by nature.&lt;/p&gt;

&lt;p&gt;Practical use cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logger:&lt;/strong&gt; If every class creates its own logger object, writing to a single log file concurrently can result in overwrites and corrupted data. A Singleton logger coordinates all file writes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration Manager:&lt;/strong&gt; You want to read an &lt;code&gt;application.properties&lt;/code&gt; file once, parse it into memory, and share it across the app. You don't want to hit the disk every time a component needs a configuration value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connection Pool Manager:&lt;/strong&gt; Database connections are expensive. A Singleton pool manager creates a fixed number of connections and hands them out to threads, ensuring the database isn't overwhelmed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache Manager:&lt;/strong&gt; An in-memory cache must be shared. If every service instantiates its own cache, they won't see each other's cached data!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Core Principles Behind Singleton
&lt;/h2&gt;

&lt;p&gt;To build a Singleton, we must actively prevent developers from using the &lt;code&gt;new&lt;/code&gt; keyword. To do this, we rely on three core principles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Private Constructor:&lt;/strong&gt; If a constructor is &lt;code&gt;private&lt;/code&gt;, no other class can call it. This absolutely prevents external instantiation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Static Instance Variable:&lt;/strong&gt; We store the single created instance in a &lt;code&gt;private static&lt;/code&gt; field. Making it &lt;code&gt;static&lt;/code&gt; ties the variable to the &lt;em&gt;class&lt;/em&gt; itself rather than to any specific object instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Public Access Method:&lt;/strong&gt; We expose a &lt;code&gt;public static&lt;/code&gt; method (usually named &lt;code&gt;getInstance()&lt;/code&gt;). This method acts as the gatekeeper. When called, it checks if the instance exists. If it does, it returns it. If it doesn't, it creates it, stores it, and &lt;em&gt;then&lt;/em&gt; returns it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Basic Singleton Implementation: Eager Initialization
&lt;/h2&gt;

&lt;p&gt;We now understand the theory, but how do we actually implement it? Let's start with the most straightforward approach: asking the Java Virtual Machine (JVM) to create the object the moment our application starts. This is known as Eager Initialization.&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="c1"&gt;// Instance is created when the class is loaded by the JVM.&lt;/span&gt;
    &lt;span class="c1"&gt;// This guarantees that only one instance exists.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;EagerSingleton&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EagerSingleton&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Private constructor prevents external instantiation.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;EagerSingleton&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Eager Singleton initialized."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Global access point to the single instance.&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;EagerSingleton&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you write an Eager Singleton, the object is brought to life the exact moment the Java ClassLoader loads the class into memory, long before any user interacts with your application. Because the JVM internally guarantees that class loading is thread-safe, we do not have to worry about concurrency issues. The &lt;code&gt;final&lt;/code&gt; keyword adds an extra layer of security, ensuring that once the instance is assigned, it can never be accidentally overwritten.&lt;/p&gt;

&lt;p&gt;When a developer eventually calls &lt;code&gt;getInstance()&lt;/code&gt;, the method simply acts as a courier, instantly returning the pre-created object.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;While eager initialization is elegantly simple and perfectly thread-safe, it introduces a glaring problem: &lt;strong&gt;Memory Leak Potential&lt;/strong&gt;. Imagine this Singleton is a complex cache manager that pre-loads large data structures, or a connection pool holding open network sockets. With Eager Initialization, the JVM allocates these heavy resources immediately on startup, even if the user never accesses the feature that requires them. We are holding precious memory hostage.&lt;/p&gt;

&lt;p&gt;To solve this problem, we need to delay the creation of the object until the precise moment it is requested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy Initialization: Saving Memory
&lt;/h2&gt;

&lt;p&gt;If Eager Initialization wastes memory, the logical evolution is Lazy Initialization. Here, we defer the object creation until a developer actively calls our access method for the very first time.&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="c1"&gt;// Instance is not created until it is first requested.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;LazySingleton&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Private constructor prevents external instantiation.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;LazySingleton&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Lazy Singleton initialized."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Creates the instance only when it is needed for the first time.&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;LazySingleton&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// If no instance exists, create one.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LazySingleton&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Return the existing instance.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this implementation, we drop the &lt;code&gt;final&lt;/code&gt; keyword and stop assigning the variable at the top. The intelligence of this pattern lives entirely within the &lt;code&gt;getInstance()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;When an application component requests the Singleton for the first time, our method evaluates the null check. Since the application just started, the instance variable is indeed null. The code gracefully steps inside the conditional block, invokes the private constructor to allocate the necessary memory, and assigns the newly minted object to our static variable. Finally, it returns the instance to the caller.&lt;/p&gt;

&lt;p&gt;The beauty of this approach shines during the &lt;em&gt;second&lt;/em&gt; request. When another component calls the method, the null check evaluates to false. The application completely skips the creation logic and instantly hands back the exact same object. We have successfully solved our memory problem. The object only exists if it is actually used.&lt;/p&gt;

&lt;p&gt;However, we have unknowingly walked right into a catastrophic architectural bug. While this basic implementation works flawlessly in a simple, single-threaded script, modern Java applications operate in highly concurrent environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;To understand why our Lazy Singleton fails in the real world, we must take a brief detour into concurrency.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;thread&lt;/strong&gt; is an independent path of execution within your application. &lt;strong&gt;Concurrency&lt;/strong&gt; occurs when multiple threads execute tasks simultaneously, driven by a multi-core CPU. A &lt;strong&gt;race condition&lt;/strong&gt; is a software bug that happens when the outcome of a program depends on the unpredictable timing of how the CPU schedules these threads.&lt;/p&gt;

&lt;p&gt;Let's visualize a scenario where Thread A and Thread B try to access our &lt;code&gt;LazySingleton&lt;/code&gt; at the exact same millisecond.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Thread A&lt;/th&gt;
&lt;th&gt;Thread B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;calls &lt;code&gt;getInstance()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;calls &lt;code&gt;getInstance()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;evaluates: &lt;code&gt;if (instance == null)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;(Result: TRUE)&lt;/td&gt;
&lt;td&gt;evaluates: &lt;code&gt;if (instance == null)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;-- CPU Context Switch --&lt;/td&gt;
&lt;td&gt;(Result: TRUE)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;enters if block&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;enters if block&lt;/td&gt;
&lt;td&gt;&lt;code&gt;instance = new LazySingleton()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;instance = new LazySingleton()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;returns Instance #1&lt;/td&gt;
&lt;td&gt;returns Instance #2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because CPU context switching is unpredictable, Thread A evaluated the condition as true but was paused before it could actually create the object. Thread B then ran, also saw a null instance, and proceeded to create the object. When Thread A woke back up, it blindly continued into the &lt;code&gt;if&lt;/code&gt; block and created a &lt;em&gt;second&lt;/em&gt; instance.&lt;/p&gt;

&lt;p&gt;Our Singleton pattern has been utterly shattered. We now have two separate objects floating in memory, violating the primary rule of the pattern. We need a way to control the traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synchronized Method: The Traffic Jam
&lt;/h2&gt;

&lt;p&gt;The most intuitive way to prevent threads from colliding in Java is to force them to form an orderly line. We do this by applying the &lt;code&gt;synchronized&lt;/code&gt; keyword to our method.&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="c1"&gt;// Instance is created only when it is first requested.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;SyncMethodSingleton&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Private constructor prevents external instantiation.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;SyncMethodSingleton&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;// Synchronized method ensures that only one thread can execute the instance creation logic at a time.&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;synchronized&lt;/span&gt; &lt;span class="nc"&gt;SyncMethodSingleton&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// Create the instance if it does not already exist.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SyncMethodSingleton&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Return the single shared instance.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding &lt;code&gt;synchronized&lt;/code&gt; to the method signature, we turn &lt;code&gt;getInstance()&lt;/code&gt; into a locked room. Only one thread can possess the key to this room at any given time. If Thread A is inside evaluating the null check, Thread B is physically blocked from entering the method and must wait patiently outside. By the time Thread B is allowed in, Thread A has finished creating the instance. Thread B will correctly see that the instance is no longer null and will simply return it.&lt;/p&gt;

&lt;p&gt;Our Singleton is finally thread-safe. But we have traded a correctness problem for a massive performance bottleneck.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Think about the lifecycle of this Singleton. We only truly need synchronization for the very first thread, the one that actually executes the constructor. Once the object exists, every subsequent read operation is perfectly safe to happen concurrently. Yet, because we synchronized the entire method, every single time any part of our app wants to read from this Singleton, threads are forced to wait in line. In a high-traffic enterprise application, this single lock can choke your entire system's throughput.&lt;/p&gt;

&lt;h2&gt;
  
  
  Double-Checked Locking
&lt;/h2&gt;

&lt;p&gt;We need a scalpel, not a sledgehammer. What if we only synchronize the exact block of code that creates the object, and only apply that lock if the object hasn't been created yet? This brings us to a highly performant idiom known as Double-Checked Locking (DCL).&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="c1"&gt;// Volatile ensures that changes made by one thread&lt;/span&gt;
    &lt;span class="c1"&gt;// are immediately visible to other threads.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="nc"&gt;DoubleCheckedSingleton&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Private constructor prevents external instantiation.&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;DoubleCheckedSingleton&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;DoubleCheckedSingleton&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// First check avoids synchronization after the instance has already been created.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

            &lt;span class="c1"&gt;// Only one thread can enter this block at a time.&lt;/span&gt;
            &lt;span class="kd"&gt;synchronized&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DoubleCheckedSingleton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="c1"&gt;// Second check ensures another thread has not already created the instance while waiting.&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DoubleCheckedSingleton&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Return the single shared instance.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The execution flow here is brilliant. When threads call &lt;code&gt;getInstance()&lt;/code&gt;, they immediately hit the first &lt;code&gt;if&lt;/code&gt; check. This check is completely lock-free. If the instance already exists, threads grab the object and go, operating at maximum speed without ever encountering a lock.&lt;/p&gt;

&lt;p&gt;If the instance is null, threads proceed to the &lt;code&gt;synchronized&lt;/code&gt; block. Suppose Thread A wins the lock while Thread B waits. Thread A enters the block and performs a &lt;em&gt;second&lt;/em&gt; null check. Why? Because while Thread A was waiting to acquire the lock, another thread might have sneaked in and created the instance! The second check ensures we don't accidentally overwrite an instance that was just established. Thread A creates the object, assigns it, and releases the lock. When Thread B finally gets the lock, it hits the second check, sees the newly created object, and safely skips the creation logic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Historically, prior to Java 5, Double-Checked Locking was considered a broken anti-pattern. The Java Memory Model was not strict enough, allowing the JVM to wildly reorder instructions in ways that caused crashes. Today, thanks to the keyword we are about to discuss, DCL is a highly respected, production-ready solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Understanding the &lt;code&gt;volatile&lt;/code&gt; Keyword
&lt;/h2&gt;

&lt;p&gt;You likely noticed the word &lt;code&gt;volatile&lt;/code&gt; attached to the instance variable in our Double-Checked Locking example. If you forget this single word during an interview or in production code, your Singleton is fundamentally broken. To understand why, we must explore the physical architecture of modern hardware.&lt;/p&gt;

&lt;p&gt;Modern multi-core CPUs are incredibly fast, much faster than the main system RAM. To bridge this speed gap, CPUs utilize ultra-fast local caches (L1, L2, L3) for each core. When a thread modifies a variable, it often writes that change to its local CPU cache to save time, rather than updating the main memory immediately.&lt;/p&gt;

&lt;p&gt;This creates a severe &lt;strong&gt;Visibility Problem&lt;/strong&gt;. If Thread A, running on Core 1, initializes the Singleton and saves it to its local cache, Thread B, running on Core 2, might look at the main memory, see that the variable is still null, and proceed to create a duplicate instance!&lt;/p&gt;

&lt;p&gt;Furthermore, to optimize performance, the Java Compiler and the CPU are allowed to perform &lt;strong&gt;Instruction Reordering&lt;/strong&gt;. The simple line &lt;code&gt;instance = new DoubleCheckedSingleton();&lt;/code&gt; is actually three separate JVM instructions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Allocate blank memory for the object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initialize the object (run the constructor).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign the memory reference to the &lt;code&gt;instance&lt;/code&gt; variable.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The JVM is fully allowed to reorder these steps to 1 -&amp;gt; 3 -&amp;gt; 2. If it does, Thread A allocates memory and assigns the reference (Step 3). At this exact microsecond, the &lt;code&gt;instance&lt;/code&gt; variable is no longer null, but the object is completely empty because the constructor hasn't run yet. Thread B comes along, hits the lock-free first check, sees a non-null instance, and tries to invoke a method on a half-baked object, triggering a catastrophic application crash.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;volatile&lt;/code&gt; keyword acts as an iron-clad disciplinarian. First, it solves the visibility problem by forcing all reads and writes of the variable to bypass the CPU cache and go straight to Main Memory. Second, it establishes a strict &lt;em&gt;happens-before&lt;/em&gt; relationship, entirely forbidding the JVM from reordering the initialization instructions. The object &lt;em&gt;must&lt;/em&gt; be fully constructed before the reference is published to the rest of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bill Pugh Singleton: A JVM Masterclass
&lt;/h2&gt;

&lt;p&gt;Double-Checked Locking is incredibly performant, but as we just saw, it requires a deep, uncomfortable understanding of memory visibility, instruction reordering, and the &lt;code&gt;volatile&lt;/code&gt; keyword. It is verbose and notoriously easy to implement incorrectly.&lt;/p&gt;

&lt;p&gt;William Pugh, a renowned computer scientist, proposed a much more elegant solution. He realized we could trick the JVM's internal class-loading mechanics into handling the synchronization for us, allowing us to achieve perfect lazy loading without using &lt;code&gt;synchronized&lt;/code&gt; blocks or &lt;code&gt;volatile&lt;/code&gt; variables.&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;BillPughSingleton&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SingletonHelper&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BillPughSingleton&lt;/span&gt; &lt;span class="no"&gt;INSTANCE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BillPughSingleton&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;BillPughSingleton&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;SingletonHelper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach utilizes a static inner helper class, and its brilliance lies in the JVM's lazy class-loading rules. When the application starts and the &lt;code&gt;BillPughSingleton&lt;/code&gt; class is loaded into memory, the JVM explicitly ignores the inner &lt;code&gt;SingletonHelper&lt;/code&gt; class. It does not load it, and therefore does not instantiate the Singleton object. We have achieved perfect lazy loading; zero memory is wasted.&lt;/p&gt;

&lt;p&gt;The magic occurs only when a developer calls &lt;code&gt;getInstance()&lt;/code&gt;. This method attempts to access &lt;code&gt;SingletonHelper.INSTANCE&lt;/code&gt;. The moment that explicit reference is made, the JVM is forced to load the inner class and initialize its static fields.&lt;/p&gt;

&lt;p&gt;Because the Java language specification strictly guarantees that the initialization of a class is thread-safe, the JVM natively locks the process behind the scenes. Multiple threads can call the method simultaneously, but the JVM will perfectly orchestrate the creation of a single object, returning it to all threads with blazing speed. For years, the Bill Pugh approach has been considered the gold standard of Java Singletons.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reflection Problem
&lt;/h2&gt;

&lt;p&gt;Our Bill Pugh Singleton is lazy, fast, and thread-safe. But in the hands of a curious or malicious developer, it can easily be destroyed. Java provides a powerful API called Reflection, which allows developers to inspect and manipulate code at runtime, completely ignoring access modifiers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReflectionBreaker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;BillPughSingleton&lt;/span&gt; &lt;span class="n"&gt;instanceOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BillPughSingleton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;BillPughSingleton&lt;/span&gt; &lt;span class="n"&gt;instanceTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Constructor&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;constructors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BillPughSingleton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeclaredConstructors&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Constructor&lt;/span&gt; &lt;span class="n"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;constructors&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// We bypass the private constructor!&lt;/span&gt;
                &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAccessible&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;instanceTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BillPughSingleton&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newInstance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instanceOne&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;instanceTwo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Prints: false&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By retrieving the private constructor and explicitly calling &lt;code&gt;setAccessible(true)&lt;/code&gt;, Reflection allows us to forcibly instantiate a second object, entirely breaking the Singleton contract.&lt;/p&gt;

&lt;p&gt;To defend against this, we must add aggressive boilerplate logic inside our constructor. We must check if an instance already exists, and if it does, forcefully throw a &lt;code&gt;RuntimeException&lt;/code&gt; to crash the rogue process before it can instantiate the duplicate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Serialization Problem
&lt;/h2&gt;

&lt;p&gt;In distributed applications, you often need to convert an object into a byte stream (Serialization) to send it over a network or save it to a database, and later reconstruct it (Deserialization).&lt;/p&gt;

&lt;p&gt;If your Singleton class implements the &lt;code&gt;Serializable&lt;/code&gt; interface, you are in for a nasty surprise. During the deserialization process, the JVM reads the byte stream and automatically creates a &lt;strong&gt;brand-new instance&lt;/strong&gt; of your Singleton, completely bypassing your private constructor.&lt;/p&gt;

&lt;p&gt;To patch this vulnerability, you must provide a special, deeply hidden JVM hook method called &lt;code&gt;readResolve()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;readResolve&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the JVM deserializes an object, it searches for the &lt;code&gt;readResolve()&lt;/code&gt; method. If it finds it, the JVM immediately discards the freshly created duplicate object and instead returns whatever &lt;code&gt;readResolve()&lt;/code&gt; dictates, in our case, the true Singleton instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cloning Problem
&lt;/h2&gt;

&lt;p&gt;Similarly, if your Singleton accidentally implements the &lt;code&gt;Cloneable&lt;/code&gt; interface (perhaps inherited from a parent class), a developer could invoke the &lt;code&gt;.clone()&lt;/code&gt; method to create a shallow copy of your precious instance.&lt;/p&gt;

&lt;p&gt;To prevent this, you must explicitly override the clone method and throw an exception to block the operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;CloneNotSupportedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CloneNotSupportedException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cloning of a Singleton is strictly prohibited."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Enum Singleton: The Indestructible Solution
&lt;/h2&gt;

&lt;p&gt;Protecting a Singleton from Reflection, Serialization, and Cloning requires writing a lot of defensive, ugly boilerplate code. Joshua Bloch, the legendary author of &lt;em&gt;Effective Java&lt;/em&gt;, looked at this mess and proposed a radically simple alternative: just use a Java Enum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;EnumSingleton&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enum Singleton is working flawlessly."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the entire code. You access it anywhere in your application by calling &lt;code&gt;EnumSingleton.INSTANCE.doSomething()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why is this considered the ultimate Singleton? Because the Java language specification treats enums like royalty. The JVM inherently guarantees that an enum value is instantiated exactly once in a given Java program. It naturally provides flawless thread-safety.&lt;/p&gt;

&lt;p&gt;If a hacker tries to use Reflection to duplicate an enum, the internal &lt;code&gt;java.lang.reflect.Constructor&lt;/code&gt; class explicitly detects it and throws an &lt;code&gt;IllegalArgumentException&lt;/code&gt;. Furthermore, Java's serialization mechanism is custom-built to ensure enum values are never duplicated during deserialization, so no &lt;code&gt;readResolve()&lt;/code&gt; hack required. While it does not support lazy loading, the Enum Singleton is the absolute safest, most robust way to implement the pattern in core Java.&lt;/p&gt;

&lt;h2&gt;
  
  
  Singleton and Class Loaders: An Enterprise Reality
&lt;/h2&gt;

&lt;p&gt;There is a frequently overlooked enterprise concept that catches even senior engineers off guard. The standard rule of the GoF Singleton pattern states: "There is only one instance per JVM." &lt;strong&gt;This is technically false in Java.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The accurate statement is: &lt;strong&gt;There is only one instance per ClassLoader.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Enterprise Java architectures (like Apache Tomcat, JBoss, or WebSphere), applications are packaged as WAR or EAR files. These heavy application servers use hierarchical, isolated class loaders. If your Singleton class is packaged into two separate WAR files deployed on the same Tomcat server, they will be loaded by two different class loaders. The JVM will treat them as entirely different classes. You will end up with multiple Singleton instances running in the exact same JVM memory space!&lt;/p&gt;

&lt;p&gt;To resolve this in traditional enterprise environments, the Singleton class must be placed in a shared library folder (like Tomcat's &lt;code&gt;lib&lt;/code&gt; directory) so it is loaded by a common parent class loader, ensuring true JVM-wide singularity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing All Singleton Implementations
&lt;/h2&gt;

&lt;p&gt;To synthesize everything we have built, let's look at how the different approaches stack up against each other:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;colgroup&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Implementation&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Thread-Safe?&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Lazy Loaded?&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Reflection Safe?&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Serialization Safe?&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Eager&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;High&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs manual check&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs &lt;code&gt;readResolve&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Basic Lazy&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;High&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs manual check&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs &lt;code&gt;readResolve&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Synchronized&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Very Low&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs manual check&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs &lt;code&gt;readResolve&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Double-Checked&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;High&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs manual check&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs &lt;code&gt;readResolve&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Bill Pugh&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;High&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs manual check&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Needs &lt;code&gt;readResolve&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Enum&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;High&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Yes (Native)&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Yes (Native)&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Singleton vs Static Utility Class
&lt;/h2&gt;

&lt;p&gt;A common debate among developers is why we go through the trouble of creating Singletons when we could just create a class full of &lt;code&gt;static&lt;/code&gt; methods and variables, much like the &lt;code&gt;java.lang.Math&lt;/code&gt; class.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;colgroup&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Singleton Object&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Static Utility Class&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Object Orientation&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;It is a real object on the heap.&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;It is not an object; just a collection of functions.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Interfaces&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Can implement interfaces (e.g., &lt;code&gt;ILogger&lt;/code&gt;).&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Cannot implement interfaces.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Inheritance&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Can extend base classes and utilize polymorphism.&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Cannot participate in traditional OOP inheritance.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;State Management&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Excellent for holding and managing complex state.&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Extremely poor. Static state is difficult to track and clear.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Can be mocked dynamically in testing frameworks.&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Very difficult to mock; requires advanced static mockers.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The Verdict:&lt;/strong&gt; If you are simply grouping stateless, utility helper methods together, use a Static Class. If your component needs to manage state, maintain active connections, or adhere to interface-driven design, you must use a Singleton.&lt;/p&gt;

&lt;h2&gt;
  
  
  Singleton in the Spring Framework
&lt;/h2&gt;

&lt;p&gt;If you are a modern Java developer, you are almost certainly using the Spring Framework. In Spring, the framework manages the lifecycle of your objects for you using a concept called Inversion of Control (IoC).&lt;/p&gt;

&lt;p&gt;When you annotate a class with &lt;code&gt;@Service&lt;/code&gt; or &lt;code&gt;@Component&lt;/code&gt;, Spring essentially registers it as a Singleton Bean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interview Tip:&lt;/strong&gt; It is crucial to understand the subtle difference between a GoF Java Singleton and a Spring Singleton. A classic Java Singleton guarantees one instance per &lt;em&gt;ClassLoader&lt;/em&gt;. A Spring Singleton guarantees one instance per &lt;em&gt;ApplicationContext&lt;/em&gt; (the Spring IoC container). If you instantiate two ApplicationContexts within the same JVM, Spring will happily create two instances of your globally intended &lt;code&gt;@Service&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because Spring handles the instantiation via Dependency Injection (DI), you completely abandon private constructors, static variables, and &lt;code&gt;getInstance()&lt;/code&gt; boilerplates. You simply write standard, testable Java classes, and let Spring enforce the single-instance rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Singleton in Modern Cloud Applications
&lt;/h2&gt;

&lt;p&gt;In the modern era of cloud-native development, applications are rarely deployed on a single massive server. They are broken down into microservices and deployed across dozens of identical Kubernetes pods.&lt;/p&gt;

&lt;p&gt;This fundamentally shifts the concept of a Singleton. A Java Singleton only exists within the memory boundary of &lt;em&gt;one specific pod&lt;/em&gt;. If you build an in-memory Singleton Cache Manager, Pod A and Pod B will have entirely disconnected, conflicting caches.&lt;/p&gt;

&lt;p&gt;If you require a true "Cluster-wide Singleton", a resource that must be perfectly singular across a massive distributed network, a Java-level Singleton will fail you. You must step out of the JVM and rely on distributed systems tools like Redis for centralized caching, ZooKeeper for consensus, or database-level row locks for state management.&lt;/p&gt;

&lt;h2&gt;
  
  
  When NOT to Use Singleton (The Anti-Pattern Debate)
&lt;/h2&gt;

&lt;p&gt;Despite its fame, many architects view the manual Singleton as an &lt;strong&gt;Anti-Pattern&lt;/strong&gt; when misused.&lt;/p&gt;

&lt;p&gt;The primary criticism is &lt;strong&gt;Hidden Dependencies&lt;/strong&gt;. If an &lt;code&gt;OrderProcessor&lt;/code&gt; class buries a call to &lt;code&gt;PaymentGateway.getInstance()&lt;/code&gt; deep inside a method, the dependency is hidden. With modern Dependency Injection, dependencies are clearly declared in the constructor, making the code self-documenting.&lt;/p&gt;

&lt;p&gt;Furthermore, Singletons introduce &lt;strong&gt;Global State&lt;/strong&gt;. If Thread A mutates data inside a Singleton, and Thread B fails because of that mutation, tracking down who changed the state is a debugging nightmare.&lt;/p&gt;

&lt;p&gt;Finally, they create a &lt;strong&gt;Testing Nightmare&lt;/strong&gt;. Because Singletons persist for the entire life of the JVM, unit tests can pollute each other. Test 1 might alter the Singleton, causing Test 2 to fail simply because it expected a clean slate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes Developers Make
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Overusing the Pattern:&lt;/strong&gt; Creating a Singleton just to pass arbitrary user data between two screens in a UI application. This creates severe memory leaks and fundamentally breaks architectural boundaries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ignoring Thread Safety:&lt;/strong&gt; Deploying a basic Lazy Singleton to a production web server, leading to silent, untraceable race conditions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Storing User Context:&lt;/strong&gt; A Singleton is global. Never, under any circumstances, store user-specific context (like an Authentication Token or a Shopping Cart) in a Singleton, or User A will start seeing User B's private data!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices for Modern Development
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prefer Dependency Injection:&lt;/strong&gt; Lean heavily on frameworks like Spring, Guice, or CDI to manage singleton lifecycles. Let the framework do the heavy lifting of instantiation and sharing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Design for Interfaces:&lt;/strong&gt; Even if you write a manual Singleton, have it implement an interface. This allows you to inject mock implementations during unit testing, preserving testability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep it Stateless:&lt;/strong&gt; The safest Singletons are those that perform operations (like routing or logging) without holding onto mutable, changing data. A stateless Singleton cannot cause state-corruption bugs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common Interview Questions and Answers
&lt;/h2&gt;

&lt;p&gt;Interviewers use the Singleton pattern as a gateway to test your deeper understanding of Java mechanics. Here is how to navigate the most common questions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What exactly is a Singleton Pattern?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; It is a creational design pattern ensuring a class has only one instance per class loader, and it provides a global point of access to that single instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do you prevent the cloning of a Singleton?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; You must explicitly override the &lt;code&gt;clone()&lt;/code&gt; method inherited from the &lt;code&gt;Object&lt;/code&gt; class and throw a &lt;code&gt;CloneNotSupportedException&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Why is Double-Checked Locking broken if you forget the&lt;/strong&gt; &lt;code&gt;volatile&lt;/code&gt; &lt;strong&gt;keyword?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; Because of instruction reordering and CPU caching visibility. Without &lt;code&gt;volatile&lt;/code&gt;, the CPU might allocate memory for the object and assign the reference before the constructor actually runs. Another thread could see a non-null reference, try to use it, and crash because the object is only partially constructed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the fundamental difference between a Spring Singleton and a Java GoF Singleton?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; A traditional GoF Java Singleton strictly guarantees one instance per JVM ClassLoader. A Spring Singleton guarantees one instance per ApplicationContext container. You can have multiple Spring containers in a single JVM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Why does Joshua Bloch recommend the Enum Singleton?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; Because the JVM natively handles all the heavy lifting. Enums are thread-safe by default, the JVM prevents instantiation via reflection (&lt;code&gt;Constructor.newInstance&lt;/code&gt; blocks enums), and it natively handles serialization without needing the &lt;code&gt;readResolve()&lt;/code&gt; hack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Is the Singleton pattern considered an anti-pattern?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; It can be. Manual Singletons introduce global state, hide class dependencies, and make isolated unit testing extremely difficult because state carries over between test cases. Modern practices heavily favor Dependency Injection over manual GoF Singletons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Singleton class in Java represents a fascinating journey through software architecture. What starts as a simple concept, a private constructor and a static variable, rapidly escalates into a deep dive into the Java Memory Model, multi-threading race conditions, CPU cache visibility, JVM class loading mechanics, and modern enterprise architecture.&lt;/p&gt;

&lt;p&gt;While modern frameworks like Spring have largely abstracted away the need to manually write complex Bill Pugh or Double-Checked Singletons, understanding &lt;em&gt;how&lt;/em&gt; to write them, &lt;em&gt;why&lt;/em&gt; concurrency breaks them, and &lt;em&gt;how&lt;/em&gt; the JVM interprets them is an absolute hallmark of a Senior Java Engineer.&lt;/p&gt;

&lt;p&gt;Remember: A pattern is only as effective as its application. Use Singletons sparingly, prioritize statelessness, lean on Dependency Injection wherever possible, and always respect the dangers of global state.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Stop Misusing POST for Search: Welcome to the HTTP QUERY Method</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Sun, 12 Jul 2026 09:26:15 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/stop-misusing-post-for-search-welcome-to-the-http-query-method-3opi</link>
      <guid>https://dev.to/ashutoshkrris/stop-misusing-post-for-search-welcome-to-the-http-query-method-3opi</guid>
      <description>&lt;p&gt;Every developer building Web APIs eventually runs into the exact same architectural wall. You need to build a search feature, an analytics dashboard, or a complex reporting tool. The user selects a dozen active filters, specifies nested conditions, chooses sorting rules, and hits "Search."&lt;/p&gt;

&lt;p&gt;Suddenly, your clean backend design faces an unpleasant choice. If you choose a traditional &lt;code&gt;GET&lt;/code&gt; request, your URL balloons into an unreadable string of encoded text that risks crashing into web browser or server character limits. If you choose a &lt;code&gt;POST&lt;/code&gt; request, you easily bypass the size limits by placing the filter data inside the request body, but you strip away the fundamental caching, safety, and retry guarantees that make HTTP work so beautifully.&lt;/p&gt;

&lt;p&gt;For decades, we treated this tension as just another normal quirk of web development. We built complex workarounds like persisted queries or query hashing, pretending that using an action verb like &lt;code&gt;POST&lt;/code&gt; to perform a read-only search was fine.&lt;/p&gt;

&lt;p&gt;That compromise is no longer necessary. The Internet Engineering Task Force (IETF) officially introduced a new standard HTTP method designed to break this deadlock: &lt;code&gt;QUERY&lt;/code&gt; &lt;strong&gt;(&lt;/strong&gt;&lt;a href="https://www.rfc-editor.org/info/rfc10008/" rel="noopener noreferrer"&gt;&lt;strong&gt;RFC 10008&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;QUERY&lt;/code&gt; method fills a massive gap in web architecture. It provides the heavy-lifting capability of a request body, while preserving the clean, read-only guarantees of a safe and idempotent fetch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why GET Isn't Always Enough
&lt;/h2&gt;

&lt;p&gt;To understand why the &lt;code&gt;QUERY&lt;/code&gt; method matters, we need to look at the practical limits of the options we have used for years.&lt;/p&gt;

&lt;p&gt;When you learn REST API design, the rule is simple: if you are reading data, you use &lt;code&gt;GET&lt;/code&gt;. This approach works flawlessly for simple lookups like &lt;code&gt;/api/v1/users/42&lt;/code&gt; or light filtering like &lt;code&gt;/products?category=shoes&amp;amp;size=10&lt;/code&gt;. The parameters are right there in the URL string. They are easy to inspect, easy to bookmark, and perfectly suited for HTTP caching layers.&lt;/p&gt;

&lt;p&gt;However, modern applications rarely stay that simple. Imagine you are building an advanced search engine or an enterprise reporting tool. Your user wants to filter products based on a highly complex query: they need items within a specific category, priced within a dynamic range, matching an array of tags, excluding clearance items, and sorted by a complex multi-column rule.&lt;/p&gt;

&lt;p&gt;If you try to map that into a standard &lt;code&gt;GET&lt;/code&gt; request, the URL starts looking like an encoded mess:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;GET /products/search?filter%5Bcategory%5D&lt;span class="o"&gt;=&lt;/span&gt;laptops&amp;amp;filter%5Bprice%5D%5Bmax%5D&lt;span class="o"&gt;=&lt;/span&gt;1500&amp;amp;filter%5Btags%5D%5B0%5D&lt;span class="o"&gt;=&lt;/span&gt;ssd&amp;amp;filter%5Btags%5D%5B1%5D&lt;span class="o"&gt;=&lt;/span&gt;business&amp;amp;sort&lt;span class="o"&gt;=&lt;/span&gt;price&amp;amp;order&lt;span class="o"&gt;=&lt;/span&gt;desc HTTP/1.1
Host: query-demo-self.vercel.app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach presents four distinct architectural problems outlined in RFC 10008:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;URL Length Limitations:&lt;/strong&gt; While the HTTP specification doesn't enforce a hard limit on URL length, the real-world infrastructure handling your traffic does. Browsers, load balancers, corporate firewalls, and Content Delivery Networks (CDNs) often truncate or reject URLs that exceed a certain size—frequently capping out around 8,000 octets (bytes). If a user pastes a massive list of IDs into a search filter, a &lt;code&gt;GET&lt;/code&gt; request will simply fail.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Privacy and Data Leakage:&lt;/strong&gt; URLs are designed to be visible. Because query strings live directly inside the request target, they are automatically logged in plain text by web servers, stored in browser history files, and passed along in &lt;code&gt;Referer&lt;/code&gt; headers to third-party scripts. If your search query contains sensitive filters—like an account number, a medical symptom, or personal data—that information leaks across your infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encoding Overhead:&lt;/strong&gt; Expressing complex data structures inside a target URI is highly inefficient because of the overhead of percent-encoding brackets, spaces, and special characters, making network payloads harder to read and debug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Dilution:&lt;/strong&gt; Encoding every single query combination directly into the request URI effectively casts every unique combination of query inputs as entirely distinct resources on the web, cluttering resource organization.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Faced with these limits, many developers ask a logical question: &lt;em&gt;Why not just send a request body inside a standard&lt;/em&gt; &lt;code&gt;GET&lt;/code&gt; &lt;em&gt;request?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The short answer is that the web infrastructure treats &lt;code&gt;GET&lt;/code&gt; bodies as having &lt;strong&gt;no defined semantic meaning&lt;/strong&gt;. Because of this ambiguity, the ecosystem handles it completely inconsistently. Some proxy servers silently strip the body before passing the request forward. Other API gateways reject the request entirely, while some frameworks ignore the body. Altering how &lt;code&gt;GET&lt;/code&gt; processes bodies today would break millions of legacy network systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why POST Isn't the Ideal Replacement
&lt;/h2&gt;

&lt;p&gt;Because &lt;code&gt;GET&lt;/code&gt; with a body is unusable in the wild, the industry settled on an alternative workaround: using &lt;code&gt;POST&lt;/code&gt; for complex searches.&lt;/p&gt;

&lt;p&gt;When you use &lt;code&gt;POST&lt;/code&gt;, all your complex filters travel cleanly inside the request body. You can send a beautifully structured JSON payload of any size, avoiding URL length limits and keeping sensitive terms out of system access logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;POST /products/search HTTP/1.1
Host: query-demo-self.vercel.app
Content-Type: application/json

&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"category"&lt;/span&gt;: &lt;span class="s2"&gt;"Laptops"&lt;/span&gt;,
  &lt;span class="s2"&gt;"price"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"max"&lt;/span&gt;: 1500 &lt;span class="o"&gt;}&lt;/span&gt;,
  &lt;span class="s2"&gt;"tags"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ssd"&lt;/span&gt;, &lt;span class="s2"&gt;"business"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
  &lt;span class="s2"&gt;"sort"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"field"&lt;/span&gt;: &lt;span class="s2"&gt;"price"&lt;/span&gt;, &lt;span class="s2"&gt;"order"&lt;/span&gt;: &lt;span class="s2"&gt;"desc"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works around the immediate structural limits, but it introduces a major flaw into your API's network behavior: &lt;code&gt;POST&lt;/code&gt; &lt;strong&gt;is semantically unsafe and non-idempotent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the language of HTTP, a method is considered &lt;strong&gt;safe&lt;/strong&gt; if it does not change the state of the resource on the server. A method is &lt;strong&gt;idempotent&lt;/strong&gt; if executing it multiple times produces the identical result and state as executing it exactly once.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;POST&lt;/code&gt; is designed for state-altering actions, like creating a new database record or processing a credit card payment, network intermediaries must assume that every &lt;code&gt;POST&lt;/code&gt; request changes something on your server. This structural assumption breaks two core performance optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Caches Are Bypassed:&lt;/strong&gt; Because a &lt;code&gt;POST&lt;/code&gt; request is assumed to modify state, edge networks, CDNs, and browser caches will not cache the response by default. If a thousand users execute the exact same complex dashboard query within a minute, your origin server must compute that identical database search a thousand times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic Retries Are Blocked:&lt;/strong&gt; If a network connection drops mid-request while a browser is sending a &lt;code&gt;POST&lt;/code&gt; request, the browser cannot safely retry it automatically. Doing so might cause a double-charge or a duplicate record. The browser is forced to display a warning to the user, even if the backend endpoint was completely read-only.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How QUERY Solves the Problem
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;QUERY&lt;/code&gt; method defined in RFC 10008 directly resolves this tension. It serves as a semantic hybrid: it provides the robust request body capability of a &lt;code&gt;POST&lt;/code&gt;, while strictly maintaining the safe, idempotent, and cacheable contracts of a &lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When an endpoint uses &lt;code&gt;QUERY&lt;/code&gt;, the protocol guarantees to every proxy, browser, and CDN along the route that the operation is entirely read-only. If a connection drops, your client library can seamlessly replay the request without risk. If an edge proxy sees identical query criteria come through a second time, it can serve a cached response immediately without waking up your origin database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax and Request Examples
&lt;/h2&gt;

&lt;p&gt;To see how this works in practice, let's look at a raw HTTP representation of a &lt;code&gt;QUERY&lt;/code&gt; request alongside its response.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Request
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;QUERY /products/search HTTP/1.1
Host: query-demo-self.vercel.app
Content-Type: application/json
Accept: application/json
Accept-Query: application/json

&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"category"&lt;/span&gt;: &lt;span class="s2"&gt;"Laptops"&lt;/span&gt;,
  &lt;span class="s2"&gt;"brands"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"TechNova"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
  &lt;span class="s2"&gt;"price"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"min"&lt;/span&gt;: 500, &lt;span class="s2"&gt;"max"&lt;/span&gt;: 1500 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike a classic &lt;code&gt;GET&lt;/code&gt;, the &lt;code&gt;QUERY&lt;/code&gt; method requires a &lt;code&gt;Content-Type&lt;/code&gt; header. The specification explicitly dictates that if a client sends a &lt;code&gt;QUERY&lt;/code&gt; request without a &lt;code&gt;Content-Type&lt;/code&gt;, or if the header doesn't match the format of the body, the server MUST fail the request.&lt;/p&gt;

&lt;p&gt;Notice the &lt;code&gt;Accept-Query&lt;/code&gt; header. This allows the server to advertise exactly which query formats it knows how to parse for that endpoint—whether that is JSON, SQL, or a custom format.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Response
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age&lt;span class="o"&gt;=&lt;/span&gt;3600
Content-Location: /products/search/results/a1b2c3d4
Location: /products/search/stored-queries/42

&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"count"&lt;/span&gt;: 2,
  &lt;span class="s2"&gt;"query"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"brands"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"TechNova"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
    &lt;span class="s2"&gt;"category"&lt;/span&gt;: &lt;span class="s2"&gt;"Laptops"&lt;/span&gt;,
    &lt;span class="s2"&gt;"price"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"max"&lt;/span&gt;: 1500, &lt;span class="s2"&gt;"min"&lt;/span&gt;: 500 &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
  &lt;span class="s2"&gt;"results"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"id"&lt;/span&gt;: 1,
      &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"UltraBook Pro 14"&lt;/span&gt;,
      &lt;span class="s2"&gt;"category"&lt;/span&gt;: &lt;span class="s2"&gt;"Laptops"&lt;/span&gt;,
      &lt;span class="s2"&gt;"brand"&lt;/span&gt;: &lt;span class="s2"&gt;"TechNova"&lt;/span&gt;,
      &lt;span class="s2"&gt;"price"&lt;/span&gt;: 1299,
      &lt;span class="s2"&gt;"rating"&lt;/span&gt;: 4.8,
      &lt;span class="s2"&gt;"stock"&lt;/span&gt;: 32,
      &lt;span class="s2"&gt;"discount"&lt;/span&gt;: 15,
      &lt;span class="s2"&gt;"available"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
      &lt;span class="s2"&gt;"tags"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ssd"&lt;/span&gt;, &lt;span class="s2"&gt;"lightweight"&lt;/span&gt;, &lt;span class="s2"&gt;"business"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
      &lt;span class="s2"&gt;"specs"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"cpu"&lt;/span&gt;: &lt;span class="s2"&gt;"Intel Core Ultra 7"&lt;/span&gt;, &lt;span class="s2"&gt;"ram"&lt;/span&gt;: 32, &lt;span class="s2"&gt;"storage"&lt;/span&gt;: 1024, &lt;span class="s2"&gt;"color"&lt;/span&gt;: &lt;span class="s2"&gt;"Silver"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"id"&lt;/span&gt;: 3,
      &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"OfficeBook Air"&lt;/span&gt;,
      &lt;span class="s2"&gt;"category"&lt;/span&gt;: &lt;span class="s2"&gt;"Laptops"&lt;/span&gt;,
      &lt;span class="s2"&gt;"brand"&lt;/span&gt;: &lt;span class="s2"&gt;"TechNova"&lt;/span&gt;,
      &lt;span class="s2"&gt;"price"&lt;/span&gt;: 799,
      &lt;span class="s2"&gt;"rating"&lt;/span&gt;: 4.3,
      &lt;span class="s2"&gt;"stock"&lt;/span&gt;: 50,
      &lt;span class="s2"&gt;"discount"&lt;/span&gt;: 20,
      &lt;span class="s2"&gt;"available"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
      &lt;span class="s2"&gt;"tags"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"office"&lt;/span&gt;, &lt;span class="s2"&gt;"budget"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
      &lt;span class="s2"&gt;"specs"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"cpu"&lt;/span&gt;: &lt;span class="s2"&gt;"Intel Core i5"&lt;/span&gt;, &lt;span class="s2"&gt;"ram"&lt;/span&gt;: 16, &lt;span class="s2"&gt;"storage"&lt;/span&gt;: 512, &lt;span class="s2"&gt;"color"&lt;/span&gt;: &lt;span class="s2"&gt;"Gray"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server processes the request payload, runs the search logic, and returns a standard &lt;code&gt;200 OK&lt;/code&gt; status with the data array.&lt;/p&gt;

&lt;p&gt;The inclusion of the &lt;code&gt;Content-Location&lt;/code&gt; and &lt;code&gt;Location&lt;/code&gt; headers are incredibly powerful features of the specification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Content-Location&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt; Provides a direct URL pointing to a resource representing these specific &lt;em&gt;results&lt;/em&gt;. A client can perform a standard &lt;code&gt;GET&lt;/code&gt; request directly on that URL later to fetch the same snapshot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Location&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt; Points to the &lt;em&gt;equivalent resource&lt;/em&gt; representing the query itself. A client can send a &lt;code&gt;GET&lt;/code&gt; request to this URI to repeat the same search operation later without resending the large query body.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical Code Examples
&lt;/h2&gt;

&lt;p&gt;Let's look at how to implement and use the &lt;code&gt;QUERY&lt;/code&gt; method using modern development tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Sending a QUERY Request using cURL
&lt;/h3&gt;

&lt;p&gt;You can test a &lt;code&gt;QUERY&lt;/code&gt; endpoint directly from your terminal using standard &lt;code&gt;cURL&lt;/code&gt;. We explicitly set the method to &lt;code&gt;QUERY&lt;/code&gt;, provide the mandatory content headers, and pass our payload using the data flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; QUERY https://query-demo-self.vercel.app/products/search &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"category": "Laptops", "tags": ["gaming"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this approach is useful:&lt;/strong&gt; Because &lt;code&gt;QUERY&lt;/code&gt; is officially registered in the IANA HTTP methods registry, modern command-line utilities and network tools handle it natively without needing custom transport hacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Fetch API Example (JavaScript)
&lt;/h3&gt;

&lt;p&gt;Modern web browsers allow you to pass arbitrary method names into the standard &lt;code&gt;Fetch API&lt;/code&gt;. Here is how you can issue a &lt;code&gt;QUERY&lt;/code&gt; request from client-side code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;searchProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Laptops&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://query-demo-self.vercel.app/products/search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;QUERY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPayload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Found &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; items:`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to execute search:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script looks almost identical to a standard &lt;code&gt;POST&lt;/code&gt; implementation. However, behind the scenes, the browser knows that this request is safe and idempotent. If the network drops while waiting for the response, the underlying network engine can automatically handle retrying the operation safely.&lt;/p&gt;

&lt;h2&gt;
  
  
  QUERY vs GET vs POST
&lt;/h2&gt;

&lt;p&gt;Choosing the right tool for the job becomes much easier when we contrast the three methods side by side:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;colgroup&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Architectural Property&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;GET&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;POST&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;QUERY&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Request Body Allowed&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;No (Undefined Semantics)&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Safe (Read-Only)&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Potentially No&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Idempotent (Safe to Retry)&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Potentially No&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Default Cacheable&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;No (Only future GET/HEAD)&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Yes (Requires Body-Aware Keying)&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Data Payload Location&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;URL Query String&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Request Body&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Request Body&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Primary Use Case&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Simple, short resource reads&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Resource creation &amp;amp; mutation&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Complex, large, or private reads&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Current Support and Considerations
&lt;/h2&gt;

&lt;p&gt;While RFC 10008 represents a massive leap forward for clean API design, deploying it in production requires an honest look at the current state of network infrastructure. Because it is a newer standard, adoption is an evolving process across the web ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Caching Challenge
&lt;/h3&gt;

&lt;p&gt;Traditional caching proxies and CDNs use the request URL as the unique identifier—the "cache key"—to look up a stored response. For &lt;code&gt;QUERY&lt;/code&gt;, this model breaks down completely. Two requests to &lt;code&gt;/products/search&lt;/code&gt; could contain entirely different JSON filtering bodies, meaning they require completely different responses.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;QUERY&lt;/code&gt; caching to work safely, edge proxies must update their caching engines to fold the request body into the cache key calculation. While backend frameworks and language ecosystems have moved quickly to add native &lt;code&gt;QUERY&lt;/code&gt; support, many edge networks and CDNs are still updating their systems to handle body-aware caching at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security and Middleboxes
&lt;/h3&gt;

&lt;p&gt;Older Web Application Firewalls (WAFs) and load balancers operate on strict allowlists of classic HTTP verbs (&lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;). When an unconfigured security gateway encounters a &lt;code&gt;QUERY&lt;/code&gt; request, it might react unpredictably—either blocking the traffic outright as a potential exploit attempt, or failing to inspect the body because it treats it like a standard &lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, a &lt;code&gt;QUERY&lt;/code&gt; request from user agents implementing Cross-Origin Resource Sharing (CORS) will automatically require a "preflight" &lt;code&gt;OPTIONS&lt;/code&gt; request, as &lt;code&gt;QUERY&lt;/code&gt; does not belong to the basic set of CORS-safelisted methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Adopting QUERY
&lt;/h2&gt;

&lt;p&gt;If you want to start integrating the &lt;code&gt;QUERY&lt;/code&gt; method into your current systems, use these design strategies to ensure a smooth transition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't Replace Simple GETs:&lt;/strong&gt; If a request fits cleanly within a standard URL without hitting size limits or exposing sensitive data, leave it as a &lt;code&gt;GET&lt;/code&gt;. &lt;code&gt;QUERY&lt;/code&gt; is designed to solve the limits of complex parameters, not to deprecate standard endpoint paths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leverage Discovery Methods:&lt;/strong&gt; Use the &lt;code&gt;OPTIONS&lt;/code&gt; method to return an &lt;code&gt;Allow: GET, QUERY, OPTIONS, HEAD&lt;/code&gt; header, cleanly signaling to clients that the resource supports the new verb.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handle Content Negotiation Failures Gracefully:&lt;/strong&gt; Follow the RFC guidelines for client errors. If a query syntax is correct but points to a non-existent field or table, return a &lt;code&gt;422 Unprocessable Content&lt;/code&gt; status code. If the media type itself isn't supported, return a &lt;code&gt;415 Unsupported Media Type&lt;/code&gt; along with the &lt;code&gt;Accept-Query&lt;/code&gt; header.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validate the Content-Type Early:&lt;/strong&gt; Always place a validation guard at the top of your route handlers. If an incoming &lt;code&gt;QUERY&lt;/code&gt; request omits the &lt;code&gt;Content-Type&lt;/code&gt; header, reject it immediately with a &lt;code&gt;400 Bad Request&lt;/code&gt; or &lt;code&gt;415&lt;/code&gt; status code to stay aligned with the official specification rules.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;The introduction of the &lt;code&gt;QUERY&lt;/code&gt; method solves a structural compromise that engineers have accepted for decades. By merging the data payload flexibility of a request body with the strict safety and idempotency rules of a read operation, it removes the need to misuse &lt;code&gt;POST&lt;/code&gt; for complex searches.&lt;/p&gt;

&lt;p&gt;While full integration across every browser, WAF, and CDN proxy will take time, the establishment of RFC 10008 gives developers a standardized foundation to build cleaner, more predictable, and more efficient APIs.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>ai</category>
    </item>
    <item>
      <title>Build AI Apps with Gradio: Turn Your Python Scripts into Web Apps</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Sun, 24 May 2026 11:15:27 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/build-ai-apps-with-gradio-turn-your-python-scripts-into-web-apps-36gk</link>
      <guid>https://dev.to/ashutoshkrris/build-ai-apps-with-gradio-turn-your-python-scripts-into-web-apps-36gk</guid>
      <description>&lt;p&gt;You build a machine learning model or a chatbot in Python. It works perfectly. The logic is solid, the API calls are fast, and the responses are exactly what you want.&lt;/p&gt;

&lt;p&gt;But there is a problem. The entire experience is stuck inside a terminal.&lt;/p&gt;

&lt;p&gt;Terminal interfaces are great for learning and debugging. However, nobody wants to impress users, stakeholders, or teammates with a blinking terminal cursor forever. Real users expect web interfaces with buttons, text boxes, and clean layouts.&lt;/p&gt;

&lt;p&gt;Building a modern frontend app from scratch takes time. You have to set up React, configure a backend framework like FastAPI, manage CORS issues, and write API endpoints just to show a simple text generation result. This frontend work drastically slows down experimentation. AI engineers need to build fast prototypes, test ideas, and share them immediately.&lt;/p&gt;

&lt;p&gt;This is where Gradio comes in.&lt;/p&gt;

&lt;p&gt;Gradio basically lets Python developers cosplay as frontend developers for a day. It allows you to turn raw Python functions into interactive, shareable web applications in minutes (without writing a single line of HTML, CSS, or JavaScript).&lt;/p&gt;

&lt;p&gt;In this article, we will take a simple terminal-based Gemini chatbot and convert it into a clean, modern web application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Gradio?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.gradio.app/" rel="noopener noreferrer"&gt;Gradio&lt;/a&gt; is an open-source Python library designed specifically for building interactive web apps around machine learning models and AI scripts.&lt;/p&gt;

&lt;p&gt;You can think of Gradio as a translation layer between your Python code and a web browser. You define the inputs your function expects (like text or images) and the outputs it returns. Gradio automatically generates a user interface that matches those parameters.&lt;/p&gt;

&lt;p&gt;It has become massive in the AI community. If you visit Hugging Face Spaces (a popular platform for hosting AI demos), almost everything is built with Gradio. Developers love it because it requires minimal setup, enables fast iteration, and handles all the messy frontend logic under the hood.&lt;/p&gt;

&lt;p&gt;Here is a high-level look at how it works:&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The user types a message in the browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Gradio UI sends that text to your Python backend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your Python function processes the text (calling the Google Gemini API).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The API returns the response to your function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gradio automatically updates the web UI with the new data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installing and Setting Up Gradio
&lt;/h2&gt;

&lt;p&gt;Before we write code, we need a clean environment. Creating a virtual environment keeps your project dependencies isolated from the rest of your system.&lt;/p&gt;

&lt;p&gt;Open your terminal and run these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a virtual environment&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv ai_app_env

&lt;span class="c"&gt;# Activate the environment (Mac/Linux)&lt;/span&gt;
&lt;span class="nb"&gt;source &lt;/span&gt;ai_app_env/bin/activate

&lt;span class="c"&gt;# Activate the environment (Windows)&lt;/span&gt;
ai_app_env&lt;span class="se"&gt;\S&lt;/span&gt;cripts&lt;span class="se"&gt;\a&lt;/span&gt;ctivate

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;gradio google-genai python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are installing &lt;code&gt;gradio&lt;/code&gt; for our UI framework, &lt;code&gt;google-genai&lt;/code&gt; to access the free tier of Gemini models, and &lt;code&gt;python-dotenv&lt;/code&gt; to securely manage our API keys.&lt;/p&gt;

&lt;p&gt;Instead of exposing your API key in the terminal or hardcoding it into your script, we will use a &lt;code&gt;.env&lt;/code&gt; file. This is a standard engineering practice to keep secrets safe.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;.env&lt;/code&gt; in your project folder. Go to Google AI Studio, grab your free API key, and add it to the file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GEMINI_API_KEY=your_actual_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Important: If you are using Git, make sure to add &lt;code&gt;.env&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; file so you do not accidentally publish your key to the internet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Build Your First Gradio App
&lt;/h2&gt;

&lt;p&gt;Let us start with the simplest possible example to see how Gradio wires things together. We will build an app that takes a user's name and returns a greeting.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;01_greeting_app.py&lt;/code&gt; and add this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gradio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;


&lt;span class="c1"&gt;# 1. Define the core Python logic
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;! Welcome to your first AI app.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="c1"&gt;# 2. Create the Interface
&lt;/span&gt;&lt;span class="n"&gt;demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Interface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Greeting Generator&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter your name to get a custom greeting.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 3. Launch the web server
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script introduces the most important class in the library: &lt;code&gt;gr.Interface&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fn=greet_user&lt;/code&gt;: We tell Gradio exactly which Python function to run when a user interacts with the app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;inputs="text"&lt;/code&gt;: We tell Gradio what kind of data the function expects. Because we said "text", Gradio automatically renders an HTML text box on the screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;outputs="text"&lt;/code&gt;: We tell Gradio what kind of data the function returns. Gradio renders another text box to display the result.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;demo.launch()&lt;/code&gt;: This kicks off a local web server (powered by FastAPI under the hood) and opens the connection to your browser.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the script in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python 01_greeting_app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see an output like &lt;code&gt;Running on local URL: http://127.0.0.1:7860&lt;/code&gt;. Open that link in your browser.&lt;/p&gt;

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

&lt;p&gt;Congratulations, you just built your first Gradio app. Go ahead and play around with it. Enter your name, your pet's name, or a random string of characters. It is a small step, but it is time to &lt;em&gt;greet&lt;/em&gt; your new life as an AI UI developer.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;gr.Interface&lt;/code&gt; class does the heavy lifting here. It takes three crucial arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fn&lt;/code&gt;: The Python function to run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;inputs&lt;/code&gt;: The UI component for the function's arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;outputs&lt;/code&gt;: The UI component for the function's return value.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gradio inspects this configuration and generates the HTML, wires up the API endpoints, and handles the button clicks for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Convert Terminal Logic into a Web App
&lt;/h2&gt;

&lt;p&gt;If you have ever built a Python chatbot before, you likely used a &lt;code&gt;while True:&lt;/code&gt; loop to capture user input from the terminal continuously. That works, but it scales poorly.&lt;/p&gt;

&lt;p&gt;We are going to replace the terminal loop with a Gradio chat interface. To do this, we need to handle conversation state. The Gemini API expects to see the full history of the conversation to answer context-aware questions. Gradio's &lt;code&gt;ChatInterface&lt;/code&gt; automatically tracks history, so we just need to map Gradio's history format into the format Gemini expects.&lt;/p&gt;

&lt;p&gt;Create a new file named &lt;code&gt;02_basic_chatbot.py&lt;/code&gt; for this step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gradio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.genai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;

&lt;span class="c1"&gt;# Load environment variables from the .env file
&lt;/span&gt;&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize the Gemini client (it automatically picks up the GEMINI_API_KEY env variable)
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;chat_with_ai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Convert Gradio history format to Gemini's expected types.Content format
&lt;/span&gt;    &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;human_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ai_text&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;human_text&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ai_text&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;

    &lt;span class="c1"&gt;# Append the current user message
&lt;/span&gt;    &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_message&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;

    &lt;span class="c1"&gt;# Configure system instructions
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GenerateContentConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;system_instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful engineering assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Call the free-tier Gemini model
&lt;/span&gt;    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;


&lt;span class="c1"&gt;# Create the Chat Interface
&lt;/span&gt;&lt;span class="n"&gt;demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ChatInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;chat_with_ai&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gemini Engineering Assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask me anything about Python or system design.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file introduces &lt;code&gt;gr.ChatInterface&lt;/code&gt;, which is a specialized shortcut for building chatbots. It expects your function to accept exactly two arguments: the new &lt;code&gt;user_message&lt;/code&gt; and the &lt;code&gt;history&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The trickiest part here is translating data formats. Gradio 6 formats chat history using OpenAI's standard structure (a list of dictionaries). However, the Gemini API uses its own specific object structure.&lt;/p&gt;

&lt;p&gt;Let us break down the &lt;code&gt;for msg in history:&lt;/code&gt; loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Role Mapping:&lt;/strong&gt; Gradio calls the AI an &lt;code&gt;"assistant"&lt;/code&gt;. Gemini calls it a &lt;code&gt;"model"&lt;/code&gt;. We use a simple inline &lt;code&gt;if&lt;/code&gt; statement to translate this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Text Extraction:&lt;/strong&gt; Gradio supports multimodal chat (images and text together). Because of this, it stores message content as a list of blocks. We use a list comprehension (&lt;code&gt;"".join([...])&lt;/code&gt;) to sift through the blocks, find the text ones, and combine them into a single string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Building Gemini Objects:&lt;/strong&gt; We wrap our extracted text and role inside &lt;code&gt;types.Content&lt;/code&gt; and &lt;code&gt;types.Part.from_text&lt;/code&gt;. This is strictly required by the &lt;code&gt;google-genai&lt;/code&gt; library.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the history is formatted, we append the brand-new user message, pass it to &lt;code&gt;gemini-3.5-flash&lt;/code&gt;, and return the text response. Gradio handles rendering the chat bubbles automatically.&lt;/p&gt;

&lt;p&gt;Run it using &lt;code&gt;python 02_basic_chatbot.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Play around with the chat. Ask it to explain a Python concept, write a haiku, or help you debug a script. The bottom line here is that you just built a functional web interface for a powerful LLM in under 50 lines of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Gradio Components
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gr.Interface&lt;/code&gt; and &lt;code&gt;gr.ChatInterface&lt;/code&gt; are great shortcuts, but building custom apps requires knowing the individual puzzle pieces. Gradio provides dozens of UI components.&lt;/p&gt;

&lt;p&gt;Here are the most common ones you will use in AI development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gr.Textbox&lt;/code&gt;: Used for standard text entry or displaying plain text outputs. You can configure it to have multiple lines or placeholder text.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gr.Chatbot&lt;/code&gt;: A specialized display component that renders conversation histories in a familiar text-message bubble format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gr.Button&lt;/code&gt;: Triggers Python functions when clicked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gr.Image&lt;/code&gt;: Handles image uploads via drag-and-drop or webcam, and can display images generated by computer vision models.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gr.File&lt;/code&gt;: Allows users to upload documents (PDFs, CSVs, TXT files) and passes the file path directly to your Python script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gr.Markdown&lt;/code&gt;: Renders formatted text, tables, and links to make your UI look professional.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gr.State&lt;/code&gt;: A hidden component that stores variables (like user session data or complex history) across page refreshes without displaying anything on the screen.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These components communicate with your backend automatically. When a user uploads a file, Gradio saves it to a temporary directory and hands your function the file path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Blocks
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Interface&lt;/code&gt; class is rigid. It always puts inputs on the left and outputs on the right. When you want to build a real application, you need control over the layout.&lt;/p&gt;

&lt;p&gt;This is why &lt;code&gt;gr.Blocks&lt;/code&gt; exists.&lt;/p&gt;

&lt;p&gt;Blocks give you a blank canvas. You can arrange components in rows and columns, add tabs, and assign specific click events to specific buttons.&lt;/p&gt;

&lt;p&gt;Let us rebuild our chatbot using Blocks to add a custom layout and a "Clear History" button. Create a new file named &lt;code&gt;03_custom_layout.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gradio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;respond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Dummy logic for demonstration
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I received your message: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Blocks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;# Custom Chatbot Layout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;chatbot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Chatbot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Textbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Type a message and press Enter...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;clear_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Clear Chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;### Settings&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;(Add dropdowns here later)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Hidden state to store history (Gradio 6 uses list of dicts natively)
&lt;/span&gt;    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;

    &lt;span class="c1"&gt;# Event wiring
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_turn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Format the user message exactly how Gradio 6 expects it
&lt;/span&gt;        &lt;span class="n"&gt;new_msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_message&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;
        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;  &lt;span class="c1"&gt;# Returns: clear textbox, update state, update chatbot
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ai_turn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Extract the user's actual text string from the deeply nested history block
&lt;/span&gt;        &lt;span class="n"&gt;user_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;bot_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;respond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;new_msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bot_response&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;
        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;  &lt;span class="c1"&gt;# Returns: update state, update chatbot
&lt;/span&gt;
    &lt;span class="c1"&gt;# When the user presses Enter in the text box
&lt;/span&gt;    &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_turn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chatbot&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;ai_turn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chatbot&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Clear both the hidden state and the visible UI chatbot
&lt;/span&gt;    &lt;span class="n"&gt;clear_btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="p"&gt;[]),&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chatbot&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file introduces several advanced UI concepts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Layout with&lt;/strong&gt; &lt;code&gt;with&lt;/code&gt; &lt;strong&gt;statements:&lt;/strong&gt; &lt;code&gt;gr.Blocks()&lt;/code&gt; uses Python's context managers. Everything indented under &lt;code&gt;with gr.Row():&lt;/code&gt; will be placed side-by-side horizontally. Everything indented under &lt;code&gt;with gr.Column():&lt;/code&gt; will be stacked vertically. The &lt;code&gt;scale&lt;/code&gt; argument dictates how wide the columns are relative to each other.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gr.State([])&lt;/code&gt;: In standard Python, variables inside functions disappear when the function finishes. &lt;code&gt;gr.State&lt;/code&gt; creates a persistent, hidden variable attached to the user's browser session. We use it to store our list of message dictionaries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event Chaining (&lt;/strong&gt;&lt;code&gt;.then&lt;/code&gt;&lt;strong&gt;)&lt;/strong&gt;: Look at &lt;code&gt;msg.submit(...)&lt;/code&gt;. When a user hits Enter, we first run the &lt;code&gt;user_turn&lt;/code&gt; function. This grabs the text, updates the state, and immediately clears the input box so it feels snappy. We use &lt;code&gt;.then(...)&lt;/code&gt; to immediately trigger the &lt;code&gt;ai_turn&lt;/code&gt; function right after.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Input and Output Arrays&lt;/strong&gt;: Notice how &lt;code&gt;user_turn&lt;/code&gt; returns three things: &lt;code&gt;"", history, history&lt;/code&gt;. These map directly to the output array &lt;code&gt;[msg, state, chatbot]&lt;/code&gt;. We are telling Gradio: "Set the textbox to an empty string, set the hidden state to the updated history, and set the visual chatbot to the updated history."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the code with &lt;code&gt;python 03_custom_layout.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Test this out in your browser. Type a few messages, then hit the "Clear Chat" button to watch the state reset perfectly. Welcome to the Gradio &lt;em&gt;block party&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add Streaming Responses
&lt;/h2&gt;

&lt;p&gt;Have you noticed how modern chat engines print words on the screen one by one? That is called streaming. It prevents the user from staring at a loading spinner for ten seconds while the model generates a long paragraph.&lt;/p&gt;

&lt;p&gt;Streaming improves user experience drastically. Gradio supports this natively using Python generators.&lt;/p&gt;

&lt;p&gt;Instead of using &lt;code&gt;return&lt;/code&gt; to send the final string all at once, we use &lt;code&gt;yield&lt;/code&gt; to send incremental updates. Create &lt;code&gt;04_streaming_chatbot.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gradio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.genai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stream_chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="c1"&gt;# History parsing logic remains identical to step 2
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;text_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;text_content&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;

    &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;

    &lt;span class="c1"&gt;# Enable streaming in the API call
&lt;/span&gt;    &lt;span class="n"&gt;response_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;partial_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response_stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;partial_message&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
            &lt;span class="c1"&gt;# Yielding updates the UI immediately
&lt;/span&gt;            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;partial_message&lt;/span&gt;


&lt;span class="n"&gt;demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ChatInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stream_chat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Streaming Gemini Chatbot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The structural logic here is almost identical to our basic chatbot, but the execution is totally different.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;generate_content_stream&lt;/code&gt;: Instead of calling &lt;code&gt;generate_content&lt;/code&gt; (which waits for the whole answer to be ready), we call the streaming version. This returns an iterable stream of small text chunks directly from Google's servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The&lt;/strong&gt; &lt;code&gt;for&lt;/code&gt; &lt;strong&gt;loop&lt;/strong&gt;: We iterate over every &lt;code&gt;chunk&lt;/code&gt; that arrives from the stream. We take the new text, append it to our &lt;code&gt;partial_message&lt;/code&gt; variable, and then call &lt;code&gt;yield partial_message&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;yield&lt;/code&gt; &lt;strong&gt;vs&lt;/strong&gt; &lt;code&gt;return&lt;/code&gt;: A &lt;code&gt;return&lt;/code&gt; statement ends a function immediately. A &lt;code&gt;yield&lt;/code&gt; statement pauses the function, sends the current value to Gradio, updates the frontend UI, and then resumes exactly where it left off. This is the magic that creates the typing effect.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the file with &lt;code&gt;python 04_streaming_chatbot.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ask the AI a complex question. Watch the text flow in word by word. Play around with it and enjoy that smooth &lt;em&gt;stream of consciousness&lt;/em&gt; directly from Gemini.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upload Files and Build a Simple AI Document Chat
&lt;/h2&gt;

&lt;p&gt;One of the most common AI app ideas is "chat with my document." We can build a basic version of this quickly by combining &lt;code&gt;gr.File&lt;/code&gt; with our LLM logic.&lt;/p&gt;

&lt;p&gt;We will read the contents of an uploaded text file and inject it into Gemini's system instructions. Create &lt;code&gt;05_document_qa.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gradio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.genai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;analyze_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_question&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Prevent crashing if the user clicks Ask without a file
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;file_obj&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Please upload a text file first.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Read the file text
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;file_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Inject the file contents directly into the system prompt
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GenerateContentConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;system_instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use this document context to answer questions:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;file_content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;


&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Blocks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;# Document Q&amp;amp;A App&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;file_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Upload a .txt file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;question_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Textbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask a question about the file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;submit_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;### AI Answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Using gr.Markdown allows Gemini's bold text, lists, and code blocks to render beautifully
&lt;/span&gt;    &lt;span class="n"&gt;output_markdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your answer will appear here...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;submit_btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;analyze_document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;file_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;question_input&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;output_markdown&lt;/span&gt;  &lt;span class="c1"&gt;# Send the result straight to the Markdown component
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script bridges file management and prompt engineering, and steps up our UI game.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;if file_obj is None:&lt;/code&gt;: This is a guard clause. If the user hits the "Ask" button before uploading a file, Gradio passes &lt;code&gt;None&lt;/code&gt; to our function. If we try to open &lt;code&gt;None&lt;/code&gt;, Python will crash. This clause prevents the crash and returns a helpful warning to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;file_obj.name&lt;/code&gt;: When a user drops a file into a Gradio interface, Gradio does not pass the raw binary data to your function. Instead, it securely saves the file to a temporary directory on your machine and passes you an object. Calling &lt;code&gt;.name&lt;/code&gt; retrieves the absolute file path (e.g., &lt;code&gt;/tmp/gradio/some_file.txt&lt;/code&gt;), which we can then open normally using standard Python.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;System Prompt Injection&lt;/strong&gt;: We use an f-string to literally paste the entire text of the file into the &lt;code&gt;system_instruction&lt;/code&gt;. We are essentially telling the AI: "Here is everything you need to know. Now, answer the user's question based only on this."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rendering with&lt;/strong&gt; &lt;code&gt;gr.Markdown&lt;/code&gt;: LLMs naturally respond with Markdown formatting (like &lt;code&gt;bold text&lt;/code&gt; or bulleted lists). If we use a standard &lt;code&gt;gr.Textbox&lt;/code&gt;, the user sees raw asterisks and hashes. By assigning &lt;code&gt;gr.Markdown&lt;/code&gt; to our &lt;code&gt;outputs&lt;/code&gt; array, Gradio parses the formatting automatically. &lt;em&gt;Mark&lt;/em&gt; my words, formatted text is infinitely easier to read.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the script with &lt;code&gt;python 05_document_qa.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Upload a &lt;code&gt;.txt&lt;/code&gt; file containing an article, a snippet of code, or some meeting notes, and start asking questions. Play around to see how well Gemini pulls facts from your custom context. You can officially &lt;em&gt;file this under&lt;/em&gt; "cool things I built today."&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Deploying Gradio Apps
&lt;/h2&gt;

&lt;p&gt;Building locally is fun, but you eventually need to share your work.&lt;/p&gt;

&lt;p&gt;The fastest way to share a prototype is changing your launch command in any of these scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates a public &lt;code&gt;gradio.live&lt;/code&gt; link valid for 72 hours. It tunnels traffic from the public URL directly to the Python script running on your laptop. It is perfect for showing a quick demo to a coworker over Slack.&lt;/p&gt;

&lt;p&gt;For permanent deployment, the standard route is &lt;strong&gt;Hugging Face Spaces&lt;/strong&gt;. Spaces offers free hosting tailored specifically for Gradio apps. You just create a repository, upload your specific Python file (renamed to &lt;code&gt;app.py&lt;/code&gt; for Hugging Face) and a &lt;code&gt;requirements.txt&lt;/code&gt; file, and Hugging Face handles the server configuration automatically.&lt;/p&gt;

&lt;p&gt;Remember, your &lt;code&gt;.env&lt;/code&gt; file is only for local development. When deploying to Hugging Face Spaces, you must set your &lt;code&gt;GEMINI_API_KEY&lt;/code&gt; inside the repository's settings as a hidden secret so your app continues working securely in the cloud.&lt;/p&gt;

&lt;p&gt;Keep in mind that Gradio is optimized for prototyping and internal tools. A basic Gradio app is not designed to handle thousands of concurrent users or complex authentication systems out of the box. Be realistic about your deployment goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Gradio Works Internally
&lt;/h2&gt;

&lt;p&gt;You do not need to know the internals to use Gradio, but understanding them makes debugging much easier.&lt;/p&gt;

&lt;p&gt;Under the hood, when you call &lt;code&gt;demo.launch()&lt;/code&gt;, Gradio starts a local web server using FastAPI. This server exposes API endpoints based on the functions you defined.&lt;/p&gt;

&lt;p&gt;On the frontend, Gradio serves a single-page application (built with Svelte). When a user clicks a button, the Svelte frontend sends an HTTP request to your FastAPI backend. Your Python code runs, processes the data, and returns a JSON response.&lt;/p&gt;

&lt;p&gt;If you are using streaming or long-running tasks, Gradio switches from standard HTTP requests to WebSockets. This allows a persistent, two-way connection where your Python script can continuously push text chunks to the browser without waiting for the user to request them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Beginner Mistakes
&lt;/h2&gt;

&lt;p&gt;When developers first start building AI UIs, they usually run into the same handful of issues.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Blocking the UI:&lt;/strong&gt; Python runs synchronously by default. If your API call takes 20 seconds, the Gradio UI will freeze for 20 seconds. Use asynchronous functions or generators (&lt;code&gt;yield&lt;/code&gt;) to keep the interface responsive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Forgetting State:&lt;/strong&gt; Python variables inside functions reset on every click. If you need to remember data between clicks (like chat history or user choices), you must pass it through a &lt;code&gt;gr.State&lt;/code&gt; component or the specialized history arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exposing API Keys:&lt;/strong&gt; Never hardcode your API keys into your Python scripts. Always use the &lt;code&gt;.env&lt;/code&gt; approach combined with the &lt;code&gt;python-dotenv&lt;/code&gt; package. If you upload a hardcoded key to GitHub, bots will find it in seconds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handling Large Files Badly:&lt;/strong&gt; Reading massive datasets entirely into memory will crash your app. If a user uploads a 50MB text file, reading it straight into an LLM prompt will trigger context window boundaries or network timeouts.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When to Use Gradio vs Full Frameworks
&lt;/h2&gt;

&lt;p&gt;Gradio is a specific tool for a specific job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Gradio when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You want to test an AI idea in an afternoon.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need to share a prototype with non-technical stakeholders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You are building an internal utility tool for your team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You want to host a portfolio project on Hugging Face.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Streamlit when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Your app is heavily focused on data science, charts, and dashboards rather than pure inputs and outputs. (Streamlit is another great Python UI tool, optimized slightly more for data visualization).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use FastAPI + React (Full Framework) when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You are building a production SaaS product.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need strict user authentication, database management, and complex state routing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have thousands of users and need to scale microservices.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building UIs manually for every AI experiment gets old very quickly. Gradio shines during the discovery phase of software engineering.&lt;/p&gt;

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

&lt;p&gt;The distance between an idea and a working web app has never been shorter. Gradio became popular in the AI landscape because it eliminated the frontend bottleneck for machine learning engineers.&lt;/p&gt;

&lt;p&gt;Using a free-tier API like Gemini means you can experiment with intelligent text generation models endlessly without running up an infrastructure bill. Separating your code into specific scripts like we did makes it easy to push to GitHub, build a portfolio, and reference past work.&lt;/p&gt;

&lt;p&gt;You can find all the separate Python scripts we wrote today neatly organized in this &lt;a href="https://github.com/ashutoshkrris/gradio-tutorial" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. Feel free to fork it, clone it to your local machine, and use those files as a baseline for your own projects. Take the code examples from this article and experiment. Change the system prompts, tweak the UI blocks, or try uploading different file types.&lt;/p&gt;

&lt;p&gt;The fastest way to learn AI engineering is to build things and put them out into the world. Once you turn your Python logic into a working Gradio app, share a screenshot or a screen recording of your project on Twitter/X/LinkedIn. Make sure to tag me at &lt;a href="http://x.com/ashutoshkrris" rel="noopener noreferrer"&gt;@ashutoshkrris&lt;/a&gt; so I can see what you built and help showcase your work.&lt;/p&gt;

&lt;p&gt;You have the tools. Now go build some AI apps.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.ashutoshkrris.in/build-ai-apps-with-gradio-turn-your-python-scripts-into-web-apps" rel="noopener noreferrer"&gt;Ashutosh Writes&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Spring Boot @Value Property Order Explained</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Thu, 20 Nov 2025 19:02:53 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/spring-boot-value-property-order-explained-3k2b</link>
      <guid>https://dev.to/ashutoshkrris/spring-boot-value-property-order-explained-3k2b</guid>
      <description>&lt;p&gt;If you’ve ever been in a Spring Boot interview, you’ve probably come across this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Where does Spring Boot look for &lt;code&gt;@Value("${my.property:DEFAULT_VALUE}")&lt;/code&gt;, and in what order?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first, it might sound straightforward, but it actually tests a developer’s understanding of &lt;strong&gt;how Spring Boot resolves configuration properties&lt;/strong&gt; — a concept that directly impacts how applications behave across environments.&lt;/p&gt;

&lt;p&gt;Understanding the configuration hierarchy in Spring Boot is essential because it helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Debug issues when the wrong value is picked up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Control how environment variables and external configurations override defaults.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manage different environments such as development, staging, and production in CI/CD pipelines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we’ll look at how &lt;code&gt;@Value&lt;/code&gt; works, the exact order in which Spring Boot looks for property values, and why this knowledge is crucial for building predictable and maintainable applications.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding the &lt;code&gt;@Value&lt;/code&gt; Annotation&lt;/li&gt;
&lt;li&gt;Where Does Spring Boot Look for Properties (Order of Resolution)&lt;/li&gt;
&lt;li&gt;
Example Demonstration

&lt;ul&gt;
&lt;li&gt;Step 1: Define properties in both files&lt;/li&gt;
&lt;li&gt;Step 2: Use &lt;code&gt;@Value&lt;/code&gt; in your code&lt;/li&gt;
&lt;li&gt;
Step 3: Run the application with different configurations

&lt;ul&gt;
&lt;li&gt;Case 1: Default profile (no active profile)&lt;/li&gt;
&lt;li&gt;Case 2: Active profile set to “dev”&lt;/li&gt;
&lt;li&gt;Case 3: Override from the command line&lt;/li&gt;
&lt;li&gt;Case 4: No property found anywhere&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

Common Pitfalls

&lt;ul&gt;
&lt;li&gt;1. Forgetting to Set the Active Profile&lt;/li&gt;
&lt;li&gt;2. Unintentional Property Overrides&lt;/li&gt;
&lt;li&gt;3. Confusing &lt;code&gt;@Value&lt;/code&gt; and &lt;code&gt;@ConfigurationProperties&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Interview Tip / Summary

&lt;ul&gt;
&lt;li&gt;Quick Mnemonic to Remember the Order&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Frequently Asked Questions (FAQ)

&lt;ul&gt;
&lt;li&gt;1. What happens if a property is missing and no default value is given?&lt;/li&gt;
&lt;li&gt;2. How does &lt;code&gt;@ConfigurationProperties&lt;/code&gt; differ from &lt;code&gt;@Value&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;3. Can we override properties at runtime?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding the &lt;code&gt;@Value&lt;/code&gt; Annotation
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;@Value&lt;/code&gt; annotation in Spring Boot is used to &lt;strong&gt;inject values&lt;/strong&gt; into fields directly from property sources such as &lt;code&gt;application.properties&lt;/code&gt;, &lt;code&gt;application.yml&lt;/code&gt;, environment variables, or command-line arguments. It allows you to bind configuration values to variables in your code without hardcoding them.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${my.property:DEFAULT_VALUE}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;myProperty&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;my.property&lt;/code&gt; is the &lt;strong&gt;key&lt;/strong&gt; whose value Spring Boot will try to resolve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;DEFAULT_VALUE&lt;/code&gt; is the &lt;strong&gt;fallback value&lt;/strong&gt; that will be used &lt;strong&gt;if the property is not found&lt;/strong&gt; in any configuration source.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This default value mechanism is very useful. It ensures your application does not fail to start even if a configuration is missing. Instead, Spring Boot will inject the specified default, keeping your application stable and predictable.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;@Value&lt;/code&gt; is a simple way to access configuration properties for small or single-value injections. For more complex or grouped configurations, developers often use &lt;code&gt;@ConfigurationProperties&lt;/code&gt;, which we’ll discuss later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Does Spring Boot Look for Properties (Order of Resolution)
&lt;/h2&gt;

&lt;p&gt;When you use &lt;code&gt;@Value&lt;/code&gt; or any other property injection mechanism, Spring Boot doesn’t just look in one place for configuration values. It searches across &lt;strong&gt;multiple sources&lt;/strong&gt; in a specific &lt;strong&gt;priority order&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This order determines which value is finally injected when the same property key appears in different places. The &lt;strong&gt;higher the source is in the list&lt;/strong&gt;, the &lt;strong&gt;greater its priority&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the general order in which Spring Boot resolves properties (based on the &lt;code&gt;SpringApplication&lt;/code&gt; configuration sources):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Priority&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Example / Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Command-line arguments&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;e.g. &lt;code&gt;--my.property=value&lt;/code&gt; when running the application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Java System properties&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;e.g. &lt;code&gt;-Dmy.property=value&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;OS environment variables&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;e.g. &lt;code&gt;export MY_PROPERTY=value&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Application properties or YAML files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Located in &lt;code&gt;src/main/resources/application.properties&lt;/code&gt; or &lt;code&gt;.yml&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Profile-specific configuration files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;e.g. &lt;code&gt;application-dev.properties&lt;/code&gt; when &lt;code&gt;spring.profiles.active=dev&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;External configuration files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Files located in a &lt;code&gt;/config&lt;/code&gt; directory outside the packaged JAR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;JNDI attributes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Used in servlet containers or enterprise environments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Random values&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;e.g. &lt;code&gt;${random.uuid}&lt;/code&gt;, &lt;code&gt;${random.int}&lt;/code&gt; generated by Spring Boot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Default value in code&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The fallback provided in &lt;code&gt;@Value("${my.property:default}")&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Spring Boot checks these sources &lt;strong&gt;in order&lt;/strong&gt; — from top to bottom — and uses the &lt;strong&gt;first value it finds&lt;/strong&gt; for a given property key.&lt;/p&gt;

&lt;p&gt;This hierarchy allows you to easily &lt;strong&gt;override configurations&lt;/strong&gt; at runtime without changing your code. For example, values from command-line arguments or environment variables can override those in your application files, which is especially useful for deploying the same codebase to multiple environments like development, testing, and production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Demonstration
&lt;/h2&gt;

&lt;p&gt;Let’s look at a simple example to understand how Spring Boot decides which property value to use when multiple sources define the same key.&lt;/p&gt;

&lt;p&gt;Imagine the following project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
 └─ main/resources/
     ├─ application.properties
     ├─ application-dev.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1: Define properties in both files
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;application.properties&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;HelloFromApplication&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;application-dev.properties&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;HelloFromDevProfile&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Use &lt;code&gt;@Value&lt;/code&gt; in your code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${my.property:DefaultHello}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Run the application with different configurations
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Case 1: Default profile (no active profile)
&lt;/h4&gt;

&lt;p&gt;If you run your Spring Boot app normally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; myapp.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spring Boot will load &lt;code&gt;application.properties&lt;/code&gt; and inject the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;HelloFromApplication
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Case 2: Active profile set to “dev”
&lt;/h4&gt;

&lt;p&gt;If you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; myapp.jar &lt;span class="nt"&gt;--spring&lt;/span&gt;.profiles.active&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spring Boot will load both &lt;code&gt;application.properties&lt;/code&gt; and &lt;code&gt;application-dev.properties&lt;/code&gt;, but &lt;strong&gt;the profile-specific file has higher priority&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
So the value becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;HelloFromDevProfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Case 3: Override from the command line
&lt;/h4&gt;

&lt;p&gt;Now, if you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; myapp.jar &lt;span class="nt"&gt;--my&lt;/span&gt;.property&lt;span class="o"&gt;=&lt;/span&gt;HelloFromCLI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command-line arguments take the &lt;strong&gt;highest priority&lt;/strong&gt;, so this overrides everything else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;HelloFromCLI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Case 4: No property found anywhere
&lt;/h4&gt;

&lt;p&gt;If you remove the property from all configuration files and don’t pass it as an argument, Spring Boot uses the default value given in the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;DefaultHello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example shows how Spring Boot’s property resolution order allows flexible configuration management. You can define defaults in your code, keep environment-specific values in property files, and still override them at runtime when needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Pitfalls
&lt;/h2&gt;

&lt;p&gt;Even though Spring Boot’s configuration system is powerful, it’s easy to run into small mistakes that cause unexpected behavior. Here are some common pitfalls developers face when working with &lt;code&gt;@Value&lt;/code&gt; and property resolution.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Forgetting to Set the Active Profile
&lt;/h3&gt;

&lt;p&gt;Spring Boot supports profile-specific configuration files, such as &lt;code&gt;application-dev.properties&lt;/code&gt; or &lt;code&gt;application-prod.properties&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
However, these files are only used when the corresponding profile is active. If you forget to set the profile, Spring Boot will ignore those files and fall back to the default &lt;code&gt;application.properties&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; myapp.jar &lt;span class="nt"&gt;--spring&lt;/span&gt;.profiles.active&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this argument, your &lt;code&gt;application-dev.properties&lt;/code&gt; file won’t be loaded at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Unintentional Property Overrides
&lt;/h3&gt;

&lt;p&gt;Because Spring Boot merges multiple property sources, it’s possible to &lt;strong&gt;accidentally override&lt;/strong&gt; values from one source with another.&lt;br&gt;&lt;br&gt;
A common case is when an environment variable or command-line argument unintentionally replaces a property defined in your configuration file.&lt;/p&gt;

&lt;p&gt;For instance, if your system has an environment variable named &lt;code&gt;MY_PROPERTY&lt;/code&gt;, it might override the &lt;code&gt;my.property&lt;/code&gt; key from your &lt;code&gt;.properties&lt;/code&gt; file. Always check the effective configuration when debugging unexpected values.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Confusing &lt;code&gt;@Value&lt;/code&gt; and &lt;code&gt;@ConfigurationProperties&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Both &lt;code&gt;@Value&lt;/code&gt; and &lt;code&gt;@ConfigurationProperties&lt;/code&gt; are used to inject configuration values, but they serve different purposes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;code&gt;@Value&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;@ConfigurationProperties&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Single values&lt;/td&gt;
&lt;td&gt;Grouped or structured properties&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type safety&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Strong (binds directly to fields)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supports validation&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preferred for large configs&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;@Value&lt;/code&gt; when you only need a few properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;@ConfigurationProperties&lt;/code&gt; when dealing with a group of related configurations (for example, database settings or API credentials).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choosing the right one helps keep your configuration clean, organized, and easy to maintain.&lt;/p&gt;
&lt;h2&gt;
  
  
  Interview Tip / Summary
&lt;/h2&gt;

&lt;p&gt;When asked about property resolution in Spring Boot interviews, it’s not just about recalling the list — it’s about showing that you understand how and why it works that way.&lt;/p&gt;

&lt;p&gt;Here are the key points to keep in mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Spring Boot merges multiple property sources&lt;/strong&gt; — it doesn’t rely on a single file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Higher-priority sources override lower-priority ones&lt;/strong&gt; — values from the command line or environment variables can replace those in your application files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@Value("${my.property:DEFAULT}")&lt;/code&gt; provides a safety net — the default value ensures your application runs even when the property is missing.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Quick Mnemonic to Remember the Order
&lt;/h3&gt;

&lt;p&gt;You can remember the lookup order with this simple phrase:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“CLI → System → Env → App → Default”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or think of it as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Command-line arguments
↓
System properties (-D)
↓
Environment variables
↓
Application files (.properties / .yml)
↓
Default value in code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you end your interview answer with a short, clear explanation like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Spring Boot checks multiple property sources in a specific order — starting from command-line arguments, system properties, environment variables, and application files, before finally using the default value provided in code.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;—you’ll leave a confident and lasting impression.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQ)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. What happens if a property is missing and no default value is given?
&lt;/h3&gt;

&lt;p&gt;If a property key cannot be found in any configuration source &lt;strong&gt;and&lt;/strong&gt; you haven’t provided a default value in your &lt;code&gt;@Value&lt;/code&gt; expression, Spring Boot will throw an exception during startup.&lt;br&gt;&lt;br&gt;
For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${my.property}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;my.property&lt;/code&gt; is not defined anywhere, you’ll see an error like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder &lt;span class="s1"&gt;'my.property'&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;value &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;my&lt;/span&gt;&lt;span class="p"&gt;.property&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To prevent this, always provide a fallback value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${my.property:DefaultValue}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures your application starts smoothly, even when the property is missing.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. How does &lt;code&gt;@ConfigurationProperties&lt;/code&gt; differ from &lt;code&gt;@Value&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;While both are used to inject configuration values, they are suited to different use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;@Value&lt;/code&gt; is ideal for &lt;strong&gt;single values&lt;/strong&gt; or small configurations.&lt;br&gt;&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${server.port:8080}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;@ConfigurationProperties&lt;/code&gt; is better for &lt;strong&gt;structured or grouped configurations&lt;/strong&gt;, such as database or API settings. It binds multiple related properties into a single Java object and supports validation.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ConfigurationProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, use &lt;code&gt;@Value&lt;/code&gt; for simple injections and &lt;code&gt;@ConfigurationProperties&lt;/code&gt; for larger, type-safe configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Can we override properties at runtime?
&lt;/h3&gt;

&lt;p&gt;Yes, you can override properties &lt;strong&gt;at runtime&lt;/strong&gt; without changing your code.&lt;br&gt;&lt;br&gt;
Spring Boot allows this through various property sources, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Command-line arguments&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; myapp.jar &lt;span class="nt"&gt;--server&lt;/span&gt;.port&lt;span class="o"&gt;=&lt;/span&gt;9090
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Environment variables&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SERVER_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;9090
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;System properties&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-Dserver&lt;/span&gt;.port&lt;span class="o"&gt;=&lt;/span&gt;9090 &lt;span class="nt"&gt;-jar&lt;/span&gt; myapp.jar
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These dynamic overrides are particularly useful in &lt;strong&gt;CI/CD pipelines&lt;/strong&gt; or &lt;strong&gt;cloud environments&lt;/strong&gt;, where configurations may differ between development, staging, and production.&lt;/p&gt;

</description>
      <category>java</category>
      <category>interview</category>
      <category>programming</category>
      <category>ai</category>
    </item>
    <item>
      <title>DTO vs Record in Java: Which Should You Use?</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Sun, 29 Sep 2024 19:16:58 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/dto-vs-record-in-java-which-should-you-use-34i</link>
      <guid>https://dev.to/ashutoshkrris/dto-vs-record-in-java-which-should-you-use-34i</guid>
      <description>&lt;p&gt;In Java applications, we often need to transfer data between different layers of the application, or between services. For this purpose, we use &lt;strong&gt;Data Transfer Objects (DTOs)&lt;/strong&gt;. A DTO is a simple object designed to hold data, without any complex behavior or logic. Its job is to bundle data and pass it along where needed.&lt;/p&gt;

&lt;p&gt;Now, Java introduced a new feature in &lt;strong&gt;Java 14&lt;/strong&gt;, called &lt;strong&gt;Records&lt;/strong&gt;. These are special types of classes that focus on holding data, just like DTOs. The big difference is that Records do a lot of the repetitive work for us. For example, they automatically create methods to get the data (like getters), and they handle equality checks, &lt;code&gt;toString()&lt;/code&gt;, and more. This feature became fully available in &lt;strong&gt;Java 16&lt;/strong&gt;, making Records a modern, clean way to work with data in Java.&lt;/p&gt;

&lt;p&gt;So, why are we comparing DTOs and Records? Because they both serve a similar purpose — carrying data. However, understanding when to use one over the other is important as Java continues to evolve. In this article, we’ll explore the differences and help you decide which one fits your needs better, especially if you’re working on modern Java applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
What is a DTO?

&lt;ul&gt;
&lt;li&gt;How are DTOs implemented?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

What is a Java Record?

&lt;ul&gt;
&lt;li&gt;Key Features of Java Records&lt;/li&gt;
&lt;li&gt;Why Use Records?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Comparing DTO and Record

&lt;ul&gt;
&lt;li&gt;Immutability&lt;/li&gt;
&lt;li&gt;Boilerplate Code&lt;/li&gt;
&lt;li&gt;Data Representation&lt;/li&gt;
&lt;li&gt;Customization&lt;/li&gt;
&lt;li&gt;Alignment with Functional Programming&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

When to Use DTO vs Record

&lt;ul&gt;
&lt;li&gt;When to Use DTOs&lt;/li&gt;
&lt;li&gt;When to Use Records&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Performance Considerations

&lt;ul&gt;
&lt;li&gt;Memory Efficiency&lt;/li&gt;
&lt;li&gt;Immutability and Thread-Safety&lt;/li&gt;
&lt;li&gt;Garbage Collection&lt;/li&gt;
&lt;li&gt;CPU Overhead&lt;/li&gt;
&lt;li&gt;Real-World Performance Impact&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Wrapping Up&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a DTO?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Data Transfer Object (DTO)&lt;/strong&gt; is a simple Java object that is used to move data between different parts of an application. Think of it as a container for carrying data between layers of your application. For example, in a web application, a DTO might be used to transfer data from the service layer to the controller, or from the controller to the view layer.&lt;/p&gt;

&lt;p&gt;DTOs help keep the different parts of an application separated, making the code more organized and easier to maintain. They typically don’t have any business logic or complex behavior. Instead, they just hold data.&lt;/p&gt;

&lt;h3&gt;
  
  
  How are DTOs implemented?
&lt;/h3&gt;

&lt;p&gt;DTOs are usually implemented as regular Java classes. A typical DTO includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Private fields&lt;/strong&gt; for the data it holds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Getters and Setters&lt;/strong&gt; to access and modify the data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;Constructor&lt;/strong&gt; to create the object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Override methods&lt;/strong&gt; like &lt;code&gt;toString()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;, and &lt;code&gt;equals()&lt;/code&gt; for comparing and printing the object in a meaningful way.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example of a &lt;strong&gt;UserDTO&lt;/strong&gt; class :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Objects&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Constructor&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Getters and Setters&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setAge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getEmail&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Overriding toString method for meaningful output&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"UserDTO{"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"name='"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sc"&gt;'\''&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;", age="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;", email='"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sc"&gt;'\''&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="sc"&gt;'}'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Overriding equals method for object comparison&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="n"&gt;userDTO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;userDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Overriding hashCode method&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;strong&gt;UserDTO&lt;/strong&gt; class holds information about a user: their name, age, and email. It also provides basic functionality like comparing two &lt;code&gt;UserDTO&lt;/code&gt; objects (using &lt;code&gt;equals()&lt;/code&gt;), generating a unique hash code (using &lt;code&gt;hashCode()&lt;/code&gt;), and a &lt;code&gt;toString()&lt;/code&gt; method for readable output.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With tools like Lombok, you can avoid manually writing boilerplate code while still having a fully functional DTO. However, with &lt;strong&gt;Records&lt;/strong&gt;, as we’ll explore later, Java offers an alternative that also eliminates much of the boilerplate but with a different design philosophy (immutability by default).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s how you can use the &lt;code&gt;UserDTO&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTOUsageExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ashutosh"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ashutosh@example.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Access data&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEmail&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="c1"&gt;// Using the toString() method&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Comparing records&lt;/span&gt;
        &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="n"&gt;anotherUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Vishakha"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"vishakha@example.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anotherUser&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Ashutosh
25
ashutosh@example.com
UserDTO&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Ashutosh'&lt;/span&gt;, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25, &lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ashutosh@example.com'&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What is a Java Record?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Java Records&lt;/strong&gt; are a special type of class introduced in &lt;strong&gt;Java 14&lt;/strong&gt; (as a preview feature) and fully released in &lt;strong&gt;Java 16&lt;/strong&gt;. They simplify the creation of immutable data carriers. Records are designed to hold data in a concise and readable way, and they eliminate much of the boilerplate code that traditional classes, like DTOs, require.&lt;/p&gt;

&lt;p&gt;In a traditional DTO, you manually write constructors, getters, &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;, and &lt;code&gt;toString()&lt;/code&gt; methods (as we did earlier). With Records, Java generates all of these for you automatically. This makes them ideal for simple, immutable objects whose main job is to carry data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features of Java Records
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immutable by default&lt;/strong&gt;: Once you create a record, you can't change its data (unlike DTOs, which are typically mutable).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compact syntax&lt;/strong&gt;: You declare the fields and Java generates the constructor, getters, &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;, and &lt;code&gt;toString()&lt;/code&gt; automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No setters&lt;/strong&gt;: Since records are immutable, they don’t provide setters.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s create a &lt;strong&gt;UserRecord&lt;/strong&gt; that represents the same user data as our earlier &lt;strong&gt;UserDTO&lt;/strong&gt;, but using a record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;UserRecord&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! With just one line, Java generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;constructor&lt;/strong&gt;: &lt;code&gt;new UserRecord(String name, int age, String email)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Getters&lt;/strong&gt; for each field: &lt;code&gt;name()&lt;/code&gt;, &lt;code&gt;age()&lt;/code&gt;, and &lt;code&gt;email()&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An &lt;code&gt;equals()&lt;/code&gt; method for comparing two &lt;code&gt;UserRecord&lt;/code&gt; objects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;code&gt;hashCode()&lt;/code&gt; method to generate a unique hash code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;code&gt;toString()&lt;/code&gt; method that returns a string representation like this: &lt;code&gt;UserRecord[name=Ashutosh, age=25, email=ashutosh@example.com]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how you can use the &lt;code&gt;UserRecord&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRecordUsageExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;UserRecord&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRecord&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ashutosh"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ashutosh@example.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Access data&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="c1"&gt;// Using the toString() method&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Comparing records&lt;/span&gt;
        &lt;span class="nc"&gt;UserRecord&lt;/span&gt; &lt;span class="n"&gt;anotherUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRecord&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Vishakha"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"vishakha@example.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anotherUser&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Ashutosh
25
ashutosh@example.com
UserRecord[name&lt;span class="o"&gt;=&lt;/span&gt;Ashutosh, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25, &lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ashutosh@example.com]
&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;strong&gt;UserRecord&lt;/strong&gt;, we avoided writing getters, constructors, &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;, and &lt;code&gt;toString()&lt;/code&gt; manually. Java Records offer a clean, concise way to create immutable objects that only carry data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Records?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less Boilerplate&lt;/strong&gt;: You don’t have to write repetitive code like getters or &lt;code&gt;equals()&lt;/code&gt; methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immutable by Design&lt;/strong&gt;: Ensures the data can't be changed after the object is created, making it &lt;strong&gt;safer to use in multi-threaded environments&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear Intent&lt;/strong&gt;: Using a Record clearly communicates that the object is just for carrying data, without additional behavior or logic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparing DTO and Record
&lt;/h2&gt;

&lt;p&gt;Now that we know about DTO and Records, let’s compare them in this section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Immutability
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Records&lt;/strong&gt; are &lt;strong&gt;immutable by design&lt;/strong&gt;, meaning once you create a record instance, you can’t change its data. This immutability ensures that the data remains &lt;strong&gt;consistent and thread-safe&lt;/strong&gt; without needing any extra code. For example, in a &lt;code&gt;UserRecord&lt;/code&gt;, the fields &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt;, and &lt;code&gt;email&lt;/code&gt; can be set only when the record is created, and they can't be modified afterward.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;DTOs&lt;/strong&gt; are typically &lt;strong&gt;mutable&lt;/strong&gt;, meaning their fields can be changed after the object is created. To make DTOs immutable, you would have to explicitly avoid setters or design them carefully (e.g., using final fields). Here’s how immutability looks with a record versus a traditional DTO:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record&lt;/strong&gt;: Immutable by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DTO&lt;/strong&gt;: Requires manual enforcement for immutability, which can lead to more complex code and potential bugs.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImmutabilityExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="n"&gt;userDTO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ashutosh"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ashutosh@example.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;userDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// DTO allows this by default.&lt;/span&gt;

        &lt;span class="nc"&gt;UserRecord&lt;/span&gt; &lt;span class="n"&gt;userRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRecord&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ashutosh"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ashutosh@example.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;userRecord&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Jane"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This would result in a compile-time error.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Boilerplate Code
&lt;/h3&gt;

&lt;p&gt;One of the biggest advantages of &lt;strong&gt;Records&lt;/strong&gt; is that they significantly &lt;strong&gt;reduce boilerplate code&lt;/strong&gt;. When using a DTO, you often have to manually write getters, setters, constructors, &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;, and &lt;code&gt;toString()&lt;/code&gt; methods. With Records, all of this is generated for you automatically.&lt;/p&gt;

&lt;p&gt;In contrast, traditional &lt;strong&gt;DTOs&lt;/strong&gt; require more manual coding. Although tools like &lt;strong&gt;Lombok&lt;/strong&gt; can help reduce the amount of boilerplate, they still don’t provide the same level of simplicity as Records. Here’s a comparison:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record&lt;/strong&gt;: Automatically generates constructor, getters, &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;, and &lt;code&gt;toString()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DTO&lt;/strong&gt;: Requires manual implementation or the use of tools like Lombok.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Representation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Records&lt;/strong&gt; provide a &lt;strong&gt;compact and concise&lt;/strong&gt; way of representing data. Since the declaration of a Record contains only the fields, the code is cleaner and easier to read. This makes it easier to maintain, especially in projects with a lot of data models.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Record: Clean and simple&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;UserRecord&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare this to a DTO, which typically has a lot more code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// DTO: More verbose&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Constructor, Getters, Setters, toString, equals, hashCode...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Records, the intent is clearer: it’s just a data carrier with no extra behavior, whereas DTOs can easily become cluttered with boilerplate or additional logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customization
&lt;/h3&gt;

&lt;p&gt;One area where &lt;strong&gt;DTOs&lt;/strong&gt; have an advantage is in &lt;strong&gt;customization&lt;/strong&gt;. DTOs allow you to add custom logic, such as data validation, transformation methods, or even business logic if needed (although this is generally discouraged in pure DTOs). For example, you could add a validation method to ensure the email field follows a valid format.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Records&lt;/strong&gt;, customization is more limited. Since they are designed to be lightweight and immutable, you can’t easily add custom methods that modify internal state or perform complex logic. If your use case requires custom behavior or logic in your data objects, DTOs offer more flexibility.&lt;/p&gt;

&lt;p&gt;Here’s a quick example of adding custom validation to a DTO:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Method to validate email format&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isValidEmail&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a &lt;strong&gt;Record&lt;/strong&gt;, this level of customization would typically be handled outside the Record itself. Records focus strictly on carrying data, while logic like validation is expected to be handled elsewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alignment with Functional Programming
&lt;/h3&gt;

&lt;p&gt;One of the key principles of &lt;strong&gt;functional programming&lt;/strong&gt; is immutability — the idea that data objects should not be changed after they are created. &lt;strong&gt;Records&lt;/strong&gt; align more closely with functional programming principles because they are &lt;strong&gt;immutable by default&lt;/strong&gt;. This makes them an ideal choice in systems that favor or adopt a functional programming style.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Records&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Designed to be immutable, which aligns with functional programming's emphasis on creating data structures that cannot change state.&lt;/li&gt;
&lt;li&gt;They promote a more declarative style, where you can pass around immutable data objects without side effects, making them predictable and easier to reason about.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In contrast, &lt;strong&gt;DTOs&lt;/strong&gt; are traditionally &lt;strong&gt;mutable&lt;/strong&gt; by nature. While it’s possible to make DTOs immutable (by avoiding setters and using final fields), it requires manual enforcement. DTOs often follow the &lt;strong&gt;object-oriented&lt;/strong&gt; paradigm, where state changes are more common.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DTOs&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More flexible in terms of mutability, which makes them better suited to imperative or object-oriented programming styles.&lt;/li&gt;
&lt;li&gt;When used in their mutable form, DTOs can lead to side effects, which is generally discouraged in functional programming.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to Use DTO vs Record
&lt;/h2&gt;

&lt;p&gt;When deciding between using a &lt;strong&gt;DTO&lt;/strong&gt; or a &lt;strong&gt;Record&lt;/strong&gt;, the choice depends largely on your specific use case, project requirements, and the version of Java you're using. Below is a breakdown of when to use each:&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use DTOs
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;When mutability is required&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
If your object’s data needs to be modified after creation, &lt;strong&gt;DTOs&lt;/strong&gt; are the better choice. DTOs are typically mutable, allowing you to change the values of fields as needed. This is useful in scenarios where data is updated throughout the lifecycle of an object.&lt;/p&gt;

&lt;p&gt;Example: In a web application, a form submission may initially create a &lt;code&gt;UserDTO&lt;/code&gt; with some fields left blank. As the user updates their profile, the &lt;code&gt;UserDTO&lt;/code&gt; may need to change accordingly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;When additional behavior or validation logic is needed&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
DTOs are more flexible when it comes to adding custom behavior like validation, transformations, or additional methods. If your data object needs logic beyond simply carrying data (e.g., verifying an email format or sanitizing input), then a DTO is more suitable.&lt;/p&gt;

&lt;p&gt;Example: Adding a method in &lt;code&gt;UserDTO&lt;/code&gt; to validate the format of an email before passing it between layers of your application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Compatibility with older versions of Java (pre-Java 16)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
If your project is running on a version of Java earlier than Java 16, you won’t be able to use Records. In these cases, you’ll need to use traditional DTOs or alternatives like Lombok to simplify the code.&lt;/p&gt;

&lt;p&gt;Example: If your application must support Java 11 or Java 8, then Records are not an option, and you’ll stick with DTOs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  When to Use Records
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;When you need a concise, immutable data carrier&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Records&lt;/strong&gt; are ideal when you need a lightweight, immutable object to carry data. Since they automatically generate essential methods (constructor, getters, &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;, and &lt;code&gt;toString()&lt;/code&gt;), they offer a clean and efficient way to represent data.&lt;/p&gt;

&lt;p&gt;Example: If you’re transferring data between services in a microservice architecture and don't need to modify the data, a &lt;code&gt;UserRecord&lt;/code&gt; would be a perfect fit.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;For read-only data transfer between layers or services&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
If your application involves passing data around without the need to modify it, using a Record is a great choice. The immutability of Records ensures that the data remains consistent, making it suitable for cases like sending data from the database to a service layer or from one service to another.&lt;/p&gt;

&lt;p&gt;Example: A Record might be used to send user data from a database layer to a REST controller in a web application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;In modern Java applications (Java 16+)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
If your project uses Java 16 or later, you can take full advantage of Records. They are designed to simplify data representation in modern Java applications and help reduce the boilerplate that comes with traditional DTOs.&lt;/p&gt;

&lt;p&gt;Example: In a Java 17 web service, you might use Records for all your data transfer needs between different layers of your application to keep the codebase concise and maintainable.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Performance Considerations
&lt;/h2&gt;

&lt;p&gt;When comparing &lt;strong&gt;DTOs&lt;/strong&gt; and &lt;strong&gt;Records&lt;/strong&gt; in terms of performance, the differences are typically minimal, but there are a few important factors to consider:&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory Efficiency
&lt;/h3&gt;

&lt;p&gt;Since &lt;strong&gt;Records&lt;/strong&gt; are compact by design, they may consume slightly less memory than traditional &lt;strong&gt;DTOs&lt;/strong&gt;. The key reason is that Records do not require the additional overhead of manually implementing getters, setters, &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;, and &lt;code&gt;toString()&lt;/code&gt; methods. All of this is generated automatically by the Java compiler in a more optimized way, resulting in a smaller memory footprint.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;DTO&lt;/strong&gt; would need separate fields and methods for each operation (&lt;code&gt;getName()&lt;/code&gt;, &lt;code&gt;setName()&lt;/code&gt;, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;Record&lt;/strong&gt; internally holds just the fields and automatically generates the necessary methods, potentially using fewer resources.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Immutability and Thread-Safety
&lt;/h3&gt;

&lt;p&gt;The immutable nature of &lt;strong&gt;Records&lt;/strong&gt; provides some inherent performance benefits, particularly in &lt;strong&gt;multi-threaded environments&lt;/strong&gt;. Since Records are immutable, they don’t require synchronization or locking mechanisms when shared between threads. This can lead to better performance in scenarios where thread contention would normally degrade performance.&lt;/p&gt;

&lt;p&gt;In contrast, if you use &lt;strong&gt;mutable DTOs&lt;/strong&gt; in multi-threaded environments, you need to ensure thread safety, either by synchronizing access or using other mechanisms, which can introduce overhead and slow down the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Garbage Collection
&lt;/h3&gt;

&lt;p&gt;Both DTOs and Records are plain Java objects (POJOs), so they are subject to the same garbage collection process. However, the &lt;strong&gt;concise nature of Records&lt;/strong&gt; could lead to slightly faster garbage collection, as fewer objects are created or held in memory. This can contribute to improved performance in long-running applications or those handling large volumes of data objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  CPU Overhead
&lt;/h3&gt;

&lt;p&gt;Since Records are auto-generated by the compiler and are optimized for performance, there may be slight &lt;strong&gt;CPU performance improvements&lt;/strong&gt; in operations such as object creation, method invocation, and comparison (&lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hashCode()&lt;/code&gt;). This is particularly true when comparing complex DTOs where developers might introduce inefficiencies in manually implemented methods. The uniformity and optimization of Records ensure that these operations are handled consistently and efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Performance Impact
&lt;/h3&gt;

&lt;p&gt;In practice, the &lt;strong&gt;performance differences&lt;/strong&gt; between DTOs and Records will likely be &lt;strong&gt;small&lt;/strong&gt; and often &lt;strong&gt;negligible&lt;/strong&gt; for most applications. The compact nature of Records might lead to slight performance gains in some scenarios, but the actual impact would only be noticeable in applications with heavy data processing, high throughput, or those running in resource-constrained environments (e.g., mobile or IoT devices).&lt;/p&gt;

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

&lt;p&gt;In this tutorial, we've explored the key differences between &lt;strong&gt;DTOs&lt;/strong&gt; and &lt;strong&gt;Records&lt;/strong&gt;, their respective use cases, and how they align with different programming paradigms like functional programming. While &lt;strong&gt;DTOs&lt;/strong&gt; offer flexibility, mutability, and custom behavior, &lt;strong&gt;Records&lt;/strong&gt; provide a concise and immutable way to model data, making them ideal for modern Java applications.&lt;/p&gt;

&lt;p&gt;The decision to use a &lt;strong&gt;DTO&lt;/strong&gt; or a &lt;strong&gt;Record&lt;/strong&gt; ultimately depends on your specific requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you need &lt;strong&gt;mutability&lt;/strong&gt; or want to add custom logic, DTOs are a better fit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you prefer a &lt;strong&gt;compact, immutable structure&lt;/strong&gt; and are working in Java 16 or later, &lt;strong&gt;Records&lt;/strong&gt; offer a cleaner and more efficient option.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both approaches have their strengths, and understanding when to use each will help you write more efficient and maintainable Java code.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Simplify Your DEV Posts with Table of Contents Generator</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Tue, 06 Aug 2024 19:26:02 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/simplify-your-writing-workflow-with-table-of-contents-generator-592</link>
      <guid>https://dev.to/ashutoshkrris/simplify-your-writing-workflow-with-table-of-contents-generator-592</guid>
      <description>&lt;p&gt;Organizing content for clarity and ease of navigation is essential in the digital age. Whether you're writing a comprehensive article, a well-structured table of contents (TOC) can significantly enhance the readability of your content. &lt;a href="https://toc-generator.ashutoshkrris.in/" rel="noopener noreferrer"&gt;TOC Generator&lt;/a&gt; makes generating TOCs effortless, helping you focus on content creation rather than formatting. This article will explain how this tool can assist you and guide you through the process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why Use a Table of Contents?&lt;/li&gt;
&lt;li&gt;Key Features of the Application&lt;/li&gt;
&lt;li&gt;How to Use the TOC Generator for freeCodeCamp&lt;/li&gt;
&lt;li&gt;How to Use the TOC Generator for Markdown&lt;/li&gt;
&lt;li&gt;Benefits of Using Our Application&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Use a Table of Contents?&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Navigation:&lt;/strong&gt; TOCs allow readers to quickly jump to sections of interest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Readability:&lt;/strong&gt; A clear structure helps understand the document's flow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Better SEO:&lt;/strong&gt; Well-organized content is more likely to rank higher in search engines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Key Features of the Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supports freeCodeCamp Draft Posts:&lt;/strong&gt; Easily generate TOCs for your drafts using the platform's unique URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Markdown Support:&lt;/strong&gt; Quickly convert your Markdown headers into a clickable TOC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User-Friendly Interface:&lt;/strong&gt; Simple and intuitive design for a seamless experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a demo of the application:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/P5_nhLBcgEk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How to Use the TOC Generator for freeCodeCamp&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Access the Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Visit the &lt;a href="https://toc-generator.ashutoshkrris.in/" rel="noopener noreferrer"&gt;TOC Generator&lt;/a&gt; website.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Select the Level&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Choose the "Single Level" or "Multi-Level" as per your choice.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enter the Article URL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Input your freeCodeCamp draft post link. The placeholder will show an example URL format for guidance: &lt;code&gt;https://www.freecodecamp.org/news/p/f9bddb65-b444-4447-8451-b0857fecb0c2/&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate TOC&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click the "Generate TOC" button to create a structured TOC.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sample TOC with Single Level Headings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpigwcws0zswn5q4of46u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpigwcws0zswn5q4of46u.png" alt="Sample TOC with Single Level Headings" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sample TOC with Multi-Level Headings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl6w0b9s62s2q3ua6bff1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl6w0b9s62s2q3ua6bff1.png" alt="Sample TOC with Multi-Level Headings" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How to Use the TOC Generator for Markdown&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Access the Markdown TOC Generator&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Visit our &lt;a href="https://toc-generator.ashutoshkrris.in/markdown" rel="noopener noreferrer"&gt;Markdown TOC Generator&lt;/a&gt; page.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enter Your Markdown Content&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Paste or type your Markdown content into the provided textbox.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate TOC&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click "Generate TOC" to automatically generate the TOC based on your headers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Copy the TOC&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the "Copy" button to copy the TOC to your clipboard.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Benefits of Using Our Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Time-Saving:&lt;/strong&gt; Quickly generate TOCs without manual formatting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; Ensure your TOC is always formatted correctly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versatility:&lt;/strong&gt; Suitable for various platforms and content types.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My Table of Contents Generator is designed to streamline the process of organizing your content, making it easier for your readers to navigate and understand. Whether you're a freeCodeCamp contributor or a Markdown enthusiast, this tool can enhance your workflow and improve the presentation of your work. Try it out today and see how it can simplify your content creation process!&lt;/p&gt;

&lt;p&gt;Try out the tool here: &lt;a href="https://toc-generator.ashutoshkrris.in/" rel="noopener noreferrer"&gt;https://toc-generator.ashutoshkrris.in/&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun Fact: The Table of Contents of this post was also generated using the same tool.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>automation</category>
    </item>
    <item>
      <title>Comparable vs Comparator Explained in Java</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Sat, 20 Jul 2024 20:01:59 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/comparable-vs-comparator-explained-in-java-93m</link>
      <guid>https://dev.to/ashutoshkrris/comparable-vs-comparator-explained-in-java-93m</guid>
      <description>&lt;p&gt;Sorting is a fundamental operation in programming, essential for organizing data in a specific order. In Java, built-in sorting methods provide efficient ways to sort primitive data types and arrays, making it easy to manage and manipulate collections of data. For instance, you can quickly sort an array of integers or a list of strings using methods like &lt;code&gt;Arrays.sort()&lt;/code&gt; and &lt;code&gt;Collections.sort()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, when it comes to sorting custom objects, such as instances of user-defined classes, the built-in sorting methods fall short. These methods don't know how to order objects based on custom criteria. This is where Java's &lt;code&gt;Comparable&lt;/code&gt; and &lt;code&gt;Comparator&lt;/code&gt; interfaces come into play, allowing developers to define and implement custom sorting logic tailored to specific requirements.&lt;/p&gt;

&lt;p&gt;In this blog post, we'll explore how to use the &lt;code&gt;Comparable&lt;/code&gt; and &lt;code&gt;Comparator&lt;/code&gt; interfaces to sort custom objects in Java. I'll provide examples to illustrate the differences and use cases for each approach, helping you master custom sorting in your Java applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Sorting Methods for Primitive Types

&lt;ul&gt;
&lt;li&gt;Arrays.sort()&lt;/li&gt;
&lt;li&gt;Collections.sort()&lt;/li&gt;
&lt;li&gt;Limitations with Custom Classes&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Comparable Interface

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;How Comparable Allows for a Single Natural Ordering of Objects&lt;/li&gt;
&lt;li&gt;Limitations of Comparable&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Comparator Interface

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;
How Comparator Allows for Multiple Ways of Ordering Objects

&lt;ul&gt;
&lt;li&gt;Comparator by Name&lt;/li&gt;
&lt;li&gt;Comparator by Age&lt;/li&gt;
&lt;li&gt;Comparator by Weight&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

Comparable vs Comparator

&lt;ul&gt;
&lt;li&gt;Comparison&lt;/li&gt;
&lt;li&gt;
Benefits and Drawbacks of Each Approach

&lt;ul&gt;
&lt;li&gt;Comparable&lt;/li&gt;
&lt;li&gt;Comparator&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Wrapping Up&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sorting Methods for Primitive Types
&lt;/h2&gt;

&lt;p&gt;Java provides a variety of built-in sorting methods that make it easy to sort primitive data types. These methods are highly optimized and efficient, allowing you to sort arrays and collections with minimal code. For primitive types, such as integers, floating-point numbers, and characters, the &lt;code&gt;Arrays.sort()&lt;/code&gt; method is commonly used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arrays.sort()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Arrays.sort()&lt;/code&gt; method sorts the specified array into ascending numerical order. This method uses a Dual-Pivot Quicksort algorithm, which is faster and more efficient for most data sets.&lt;/p&gt;

&lt;p&gt;Let's look at an example of sorting an array of integers and characters using &lt;code&gt;Arrays.sort()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Arrays&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PrimitiveSorting&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;};&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Original array: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorted array: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="sc"&gt;'o'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'i'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'e'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'u'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'a'&lt;/span&gt; &lt;span class="o"&gt;};&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Original array: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorted array: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Original array: &lt;span class="o"&gt;[&lt;/span&gt;5, 3, 8, 2, 1]
Sorted array: &lt;span class="o"&gt;[&lt;/span&gt;1, 2, 3, 5, 8]
Original array: &lt;span class="o"&gt;[&lt;/span&gt;o, i, e, u, a]
Sorted array: &lt;span class="o"&gt;[&lt;/span&gt;a, e, i, o, u]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Collections.sort()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Collections.sort()&lt;/code&gt; method is used to sort collections such as &lt;code&gt;ArrayList&lt;/code&gt;. This method is also based on the natural ordering of the elements or a custom comparator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Collections&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CollectionsSorting&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;wordsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;wordsList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"banana"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;wordsList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"apple"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;wordsList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cherry"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;wordsList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"date"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Original list: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;wordsList&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wordsList&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorted list: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;wordsList&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original list: [banana, apple, cherry, date]
Sorted list: [apple, banana, cherry, date]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Limitations with Custom Classes
&lt;/h3&gt;

&lt;p&gt;While Java's built-in sorting methods, such as &lt;code&gt;Arrays.sort()&lt;/code&gt; and &lt;code&gt;Collections.sort()&lt;/code&gt;, are powerful and efficient for sorting primitive types and objects with natural ordering (like &lt;code&gt;String&lt;/code&gt;), they fall short when it comes to sorting custom objects. These methods do not inherently know how to order user-defined objects because there is no natural way for them to compare these objects.&lt;/p&gt;

&lt;p&gt;For example, consider a simple &lt;code&gt;Person&lt;/code&gt; class that has &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt;, and &lt;code&gt;weight&lt;/code&gt; attributes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Person [name="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", age="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", weight="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" kgs]"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try to sort a list of &lt;code&gt;Person&lt;/code&gt; objects using &lt;code&gt;Arrays.sort()&lt;/code&gt; or &lt;code&gt;Collections.sort()&lt;/code&gt;, we will encounter a compilation error because these methods do not know how to compare &lt;code&gt;Person&lt;/code&gt; objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Arrays&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Collections&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomClassSorting&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;65.5&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;75.0&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Charlie"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Original people list: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorted people list: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compilation Error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java: no suitable method found &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;java.util.List&amp;lt;tutorial.Person&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
    method java.util.Collections.&amp;lt;T&amp;gt;sort&lt;span class="o"&gt;(&lt;/span&gt;java.util.List&amp;lt;T&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt; is not applicable
      &lt;span class="o"&gt;(&lt;/span&gt;inference variable T has incompatible bounds
        equality constraints: tutorial.Person
        lower bounds: java.lang.Comparable&amp;lt;? super T&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
    method java.util.Collections.&amp;lt;T&amp;gt;sort&lt;span class="o"&gt;(&lt;/span&gt;java.util.List&amp;lt;T&amp;gt;,java.util.Comparator&amp;lt;? super T&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt; is not applicable
      &lt;span class="o"&gt;(&lt;/span&gt;cannot infer type-variable&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; T
        &lt;span class="o"&gt;(&lt;/span&gt;actual and formal argument lists differ &lt;span class="k"&gt;in &lt;/span&gt;length&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The error occurs because the &lt;code&gt;Person&lt;/code&gt; class does not implement the &lt;code&gt;Comparable&lt;/code&gt; interface, and there is no way for the sorting method to know how to compare two &lt;code&gt;Person&lt;/code&gt; objects.&lt;/p&gt;

&lt;p&gt;To sort custom objects like &lt;code&gt;Person&lt;/code&gt;, we need to provide a way to compare these objects. Java offers two main approaches to achieve this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Implementing the &lt;code&gt;Comparable&lt;/code&gt; Interface: This allows a class to define its natural ordering by implementing the &lt;code&gt;compareTo&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the &lt;code&gt;Comparator&lt;/code&gt; Interface: This allows us to create separate classes or lambda expressions to define multiple ways of comparing objects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will explore both approaches in the upcoming sections, starting with the &lt;code&gt;Comparable&lt;/code&gt; interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparable Interface
&lt;/h2&gt;

&lt;p&gt;Java provides a &lt;code&gt;Comparable&lt;/code&gt; interface to define a natural ordering for objects of a user-defined class. By implementing the &lt;code&gt;Comparable&lt;/code&gt; interface, a class can provide a single natural ordering that can be used to sort its instances. This is particularly useful when you need a default way to compare and sort objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Comparable&lt;/code&gt; interface contains a single method, &lt;code&gt;compareTo()&lt;/code&gt;, which compares the current object with the specified object for order. The method returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A negative integer if the current object is less than the specified object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero if the current object is equal to the specified object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A positive integer if the current object is greater than the specified object.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Comparable Allows for a Single Natural Ordering of Objects
&lt;/h3&gt;

&lt;p&gt;By implementing the &lt;code&gt;Comparable&lt;/code&gt; interface, a class can ensure that its objects have a natural ordering. This allows the objects to be sorted using methods like &lt;code&gt;Arrays.sort()&lt;/code&gt; or &lt;code&gt;Collections.sort()&lt;/code&gt; without the need for a separate comparator.&lt;/p&gt;

&lt;p&gt;Let's implement the &lt;code&gt;Comparable&lt;/code&gt; interface in a new &lt;code&gt;PersonV2&lt;/code&gt; class, comparing by age.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PersonV2&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Comparable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PersonV2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PersonV2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"PersonV2 [name="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", age="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", weight="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" kgs]"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PersonV2&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this implementation, the &lt;code&gt;compareTo()&lt;/code&gt; method compares the &lt;code&gt;age&lt;/code&gt; attribute of the current &lt;code&gt;PersonV2&lt;/code&gt; object with the &lt;code&gt;age&lt;/code&gt; attribute of the specified &lt;code&gt;PersonV2&lt;/code&gt; object by subtracting one age from the other. By using the expression &lt;code&gt;this.age - other.age&lt;/code&gt;, we’re effectively implementing this logic as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If &lt;code&gt;this.age&lt;/code&gt; is less than &lt;code&gt;other.age&lt;/code&gt;, the result will be negative.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If &lt;code&gt;this.age&lt;/code&gt; is equal to &lt;code&gt;other.age&lt;/code&gt;, the result will be zero.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If &lt;code&gt;this.age&lt;/code&gt; is greater than &lt;code&gt;other.age&lt;/code&gt;, the result will be positive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: We can also use &lt;code&gt;Integer.compare(this.age, other.age)&lt;/code&gt; instead of performing the arithmetic operation manually.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that the &lt;code&gt;PersonV2&lt;/code&gt; class implements the &lt;code&gt;Comparable&lt;/code&gt; interface, we can sort a list of &lt;code&gt;PersonV2&lt;/code&gt; objects using &lt;code&gt;Collections.sort()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Arrays&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Collections&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomClassSortingV2&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PersonV2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PersonV2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;65.5&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PersonV2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;75.0&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PersonV2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Charlie"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Original people list: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorted people list: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Original people list: &lt;span class="o"&gt;[&lt;/span&gt;PersonV2 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Alice, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;65.5 kgs], PersonV2 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Bob, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;75.0 kgs], PersonV2 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Charlie, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;35, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80.0 kgs]]
Sorted people list: &lt;span class="o"&gt;[&lt;/span&gt;PersonV2 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Bob, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;75.0 kgs], PersonV2 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Alice, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;65.5 kgs], PersonV2 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Charlie, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;35, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80.0 kgs]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;PersonV2&lt;/code&gt; objects are sorted in ascending order of age using the &lt;code&gt;Collections.sort()&lt;/code&gt; method, which relies on the natural ordering defined by the &lt;code&gt;compareTo()&lt;/code&gt; method in the &lt;code&gt;PersonV2&lt;/code&gt; class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of Comparable
&lt;/h3&gt;

&lt;p&gt;While the &lt;code&gt;Comparable&lt;/code&gt; interface provides a way to define a natural ordering for objects, it has several limitations that can restrict its use in practical applications. Understanding these limitations can help us determine when to use other mechanisms, such as the &lt;code&gt;Comparator&lt;/code&gt; interface, to achieve more flexible sorting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Natural Ordering&lt;/strong&gt;: The primary limitation of &lt;code&gt;Comparable&lt;/code&gt; is that it allows only one natural ordering for the objects of a class. When you implement &lt;code&gt;Comparable&lt;/code&gt;, you define a single way to compare objects, which is used whenever the objects are sorted or compared. This can be restrictive if you need to sort objects in multiple ways.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inflexibility&lt;/strong&gt;: If you need to sort objects by different attributes or in different orders, you will have to modify the class or create new implementations of &lt;code&gt;Comparable&lt;/code&gt;. This inflexibility can lead to a proliferation of comparison methods and can make the code harder to maintain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Non-Adaptable&lt;/strong&gt;: Once a class implements &lt;code&gt;Comparable&lt;/code&gt;, the natural ordering is fixed and cannot be easily changed. For instance, if your &lt;code&gt;PersonV2&lt;/code&gt; class initially sorts by age but later you need to sort by weight or name, you have to either change the &lt;code&gt;compareTo()&lt;/code&gt; method or create a new version of the class.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where the &lt;code&gt;Comparator&lt;/code&gt; interface comes into play. To define multiple ways of comparing objects, we can use the &lt;code&gt;Comparator&lt;/code&gt; interface, which we will explore in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparator Interface
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Comparator&lt;/code&gt; interface in Java provides a way to define multiple ways to compare and sort objects. Unlike the &lt;code&gt;Comparable&lt;/code&gt; interface, which allows only a single natural ordering, &lt;code&gt;Comparator&lt;/code&gt; is designed to offer flexibility by allowing multiple sorting strategies. This makes it particularly useful for scenarios where objects need to be sorted in different ways.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Comparator&lt;/code&gt; interface defines a single method, &lt;code&gt;compare()&lt;/code&gt;, which compares two objects and returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A negative integer if the first object is less than the second object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero if the first object is equal to the second object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A positive integer if the first object is greater than the second object.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This method provides a way to define custom ordering for objects without modifying the class itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Comparator Allows for Multiple Ways of Ordering Objects
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Comparator&lt;/code&gt; interface allows you to create multiple &lt;code&gt;Comparator&lt;/code&gt; instances, each defining a different ordering for objects. This flexibility means you can sort objects by various attributes or in different orders without altering the object's class.&lt;/p&gt;

&lt;p&gt;Let's implement multiple &lt;code&gt;Comparator&lt;/code&gt; instances for the &lt;code&gt;Person&lt;/code&gt; class. We'll define comparators for sorting by name, by age, and by weight. First, we need to update the &lt;code&gt;Person&lt;/code&gt; class to include getters and ensure that attributes are accessible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;getWeight&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Person [name="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", age="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", weight="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" kgs]"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Comparator by Name&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This comparator sorts &lt;code&gt;Person&lt;/code&gt; objects alphabetically by their &lt;code&gt;name&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial.comparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tutorial.Person&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Comparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PersonNameComparator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Comparator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Comparator by Age
&lt;/h4&gt;

&lt;p&gt;This comparator sorts &lt;code&gt;Person&lt;/code&gt; objects by their &lt;code&gt;age&lt;/code&gt;, in ascending order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial.comparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tutorial.Person&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Comparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PersonAgeComparator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Comparator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Comparator by Weight
&lt;/h4&gt;

&lt;p&gt;This comparator sorts &lt;code&gt;Person&lt;/code&gt; objects by their &lt;code&gt;weight&lt;/code&gt;, in ascending order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial.comparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tutorial.Person&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Comparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PersonWeightComparator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Comparator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWeight&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWeight&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, here’s how you can use these &lt;code&gt;Comparator&lt;/code&gt; instances to sort a list of &lt;code&gt;Person&lt;/code&gt; objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;tutorial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tutorial.comparator.PersonAgeComparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tutorial.comparator.PersonNameComparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tutorial.comparator.PersonWeightComparator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Arrays&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Collections&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomClassSortingV3&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;65.5&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;75.0&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Charlie"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Original people list: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PersonNameComparator&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorted people list by name: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PersonAgeComparator&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorted people list by age: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PersonWeightComparator&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sorted people list by weight: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Original people list: &lt;span class="o"&gt;[&lt;/span&gt;Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Alice, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;65.5 kgs], Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Bob, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;75.0 kgs], Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Charlie, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;35, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80.0 kgs]]
Sorted people list by name: &lt;span class="o"&gt;[&lt;/span&gt;Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Alice, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;65.5 kgs], Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Bob, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;75.0 kgs], Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Charlie, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;35, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80.0 kgs]]
Sorted people list by age: &lt;span class="o"&gt;[&lt;/span&gt;Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Bob, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;75.0 kgs], Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Alice, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;65.5 kgs], Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Charlie, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;35, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80.0 kgs]]
Sorted people list by weight: &lt;span class="o"&gt;[&lt;/span&gt;Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Alice, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;65.5 kgs], Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Bob, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;25, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;75.0 kgs], Person &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Charlie, &lt;span class="nv"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;35, &lt;span class="nv"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80.0 kgs]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;Comparator&lt;/code&gt; instances allow sorting the &lt;code&gt;Person&lt;/code&gt; objects by different attributes: name, age, and weight. This demonstrates how the &lt;code&gt;Comparator&lt;/code&gt; interface enables flexible and versatile sorting strategies for a class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparable vs Comparator
&lt;/h2&gt;

&lt;p&gt;When sorting objects in Java, you have two primary options: the &lt;code&gt;Comparable&lt;/code&gt; and &lt;code&gt;Comparator&lt;/code&gt; interfaces. Understanding the differences between these two interfaces can help you choose the right approach for your needs. Please note that this is also a &lt;strong&gt;very important interview question&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison
&lt;/h3&gt;

&lt;p&gt;Here’s a table comparing and contrasting the &lt;code&gt;Comparable&lt;/code&gt; and &lt;code&gt;Comparator&lt;/code&gt; interfaces in Java:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Comparable&lt;/th&gt;
&lt;th&gt;Comparator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Definition&lt;/td&gt;
&lt;td&gt;Provides a single, natural ordering for objects&lt;/td&gt;
&lt;td&gt;Provides multiple ways to compare objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;compareTo(T o)&lt;/td&gt;
&lt;td&gt;compare(T o1, T o2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation&lt;/td&gt;
&lt;td&gt;Implemented within the class itself&lt;/td&gt;
&lt;td&gt;Implemented outside the class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sorting Criteria&lt;/td&gt;
&lt;td&gt;One default natural ordering&lt;/td&gt;
&lt;td&gt;Multiple sorting criteria&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility&lt;/td&gt;
&lt;td&gt;Limited to one way of comparing objects&lt;/td&gt;
&lt;td&gt;Flexible; multiple comparators can be defined&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Class Modification&lt;/td&gt;
&lt;td&gt;Requires modifying the class to implement &lt;code&gt;Comparable&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Does not require modifying the class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use Case&lt;/td&gt;
&lt;td&gt;Use when there is a clear, natural ordering (e.g., sorting employees by ID)&lt;/td&gt;
&lt;td&gt;Use when different sorting orders are needed or when you cannot modify the class&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Benefits and Drawbacks of Each Approach
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Comparable&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: Provides a default sorting order that is easy to implement and use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in&lt;/strong&gt;: The natural ordering is part of the class itself, so it is always available and used by default in sorting methods.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Ordering&lt;/strong&gt;: Can only define one way to compare objects. If different sorting orders are needed, the class must be modified or additional &lt;code&gt;Comparator&lt;/code&gt; instances must be used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Class Modification&lt;/strong&gt;: Requires altering the class to implement &lt;code&gt;Comparable&lt;/code&gt;, which might not be feasible if the class is part of a library or if its natural ordering is not clear.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Comparator&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Allows for multiple sorting orders and criteria, which can be defined externally and used as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-invasive&lt;/strong&gt;: Does not require modification of the class itself, making it suitable for classes you do not control or when you need different sorting options.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: Requires creating and managing multiple &lt;code&gt;Comparator&lt;/code&gt; instances, which can add complexity to the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overhead&lt;/strong&gt;: Might introduce additional overhead if many comparators are used, especially if they are created on the fly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In summary, &lt;code&gt;Comparable&lt;/code&gt; is best used when a class has a natural ordering that makes sense for most use cases. &lt;code&gt;Comparator&lt;/code&gt;, on the other hand, provides flexibility for sorting by multiple criteria and is useful when the class does not have a natural ordering or when different sorting orders are needed. Choosing between &lt;code&gt;Comparable&lt;/code&gt; and &lt;code&gt;Comparator&lt;/code&gt; depends on your specific sorting needs and whether you need a single default order or multiple flexible sorting options.&lt;/p&gt;

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

&lt;p&gt;Understanding and utilizing both &lt;code&gt;Comparable&lt;/code&gt; and &lt;code&gt;Comparator&lt;/code&gt; can significantly enhance your ability to manage and manipulate object collections in Java. By applying these concepts, you can create more flexible and powerful sorting mechanisms.&lt;/p&gt;

&lt;p&gt;To solidify your understanding, try implementing both &lt;code&gt;Comparable&lt;/code&gt; and &lt;code&gt;Comparator&lt;/code&gt; in real-world scenarios. Experiment with different classes and sorting criteria to see how each approach works in practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links to Official Java Documentation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html" rel="noopener noreferrer"&gt;Java Comparable Interface&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html" rel="noopener noreferrer"&gt;Java Comparator Interface&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>programmingblogs</category>
      <category>coding</category>
      <category>interview</category>
    </item>
    <item>
      <title>Python One-Liners - Code Hacks You Should Know</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Thu, 30 Nov 2023 02:16:37 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/python-one-liners-code-hacks-you-should-know-2c74</link>
      <guid>https://dev.to/ashutoshkrris/python-one-liners-code-hacks-you-should-know-2c74</guid>
      <description>&lt;p&gt;Python's beauty lies in its simplicity and readability. And mastering the art of writing concise yet powerful code can significantly enhance your productivity as a developer. I'm talking about really short lines of code that do big things.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore 8 essential Python one-liners that every Pythonista should have in their toolkit. From list comprehensions to lambda functions and beyond, these techniques offer elegant solutions to common programming challenges, helping you write cleaner, more efficient code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;List Comprehension&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;List comprehension is a Pythonic way to create lists with a single line of code. It offers a concise alternative to traditional loops, enabling you to generate lists quickly and efficiently.&lt;/p&gt;

&lt;p&gt;Let's say you want to create a list containing squares of numbers from 0 to 9. Using a traditional loop, you'd do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using a traditional loop
&lt;/span&gt;&lt;span class="n"&gt;squared_numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;squared_numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;squared_numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The traditional loop method requires more lines of code and explicitly defines the iteration process, appending each squared number to the list step by step.&lt;/p&gt;

&lt;p&gt;On the other hand, list comprehension can achieve the same result in a single line, making the code more concise and readable. It condenses the loop into a clear, compact structure, generating the squared numbers directly into a list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using list comprehension
&lt;/span&gt;&lt;span class="n"&gt;squared_numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;squared_numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use list comprehensions when you need to apply a simple operation to every element in a sequence, such as transforming a list of numbers or strings.&lt;/p&gt;

&lt;p&gt;You can learn how you can pack and destructure lists in Python &lt;a href="https://blog.ashutoshkrris.in/mastering-list-destructuring-and-packing-in-python-a-comprehensive-guide" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Lambda Functions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://blog.ashutoshkrris.in/mastering-lambdas-a-guide-to-anonymous-functions-in-python" rel="noopener noreferrer"&gt;Lambda functions&lt;/a&gt;, also known as anonymous functions, allow you to create small, throwaway functions without explicitly defining them with &lt;code&gt;def&lt;/code&gt;. They are particularly useful in scenarios where a function is needed for a short operation.&lt;/p&gt;

&lt;p&gt;First, let's look at an example using &lt;code&gt;def&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using def
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, the &lt;code&gt;def&lt;/code&gt; keyword is used to define a named function &lt;code&gt;add_numbers&lt;/code&gt; explicitly. It takes an argument &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; and returns the sum of them. This traditional approach provides a named function that can be called multiple times.&lt;/p&gt;

&lt;p&gt;But when you need a function just for one-time usage, you can just define an anonymous function using the &lt;code&gt;lambda&lt;/code&gt; keyword like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using Lambda
&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It achieves the same result as &lt;code&gt;add_numbers&lt;/code&gt; but in a single line without assigning a name explicitly. Lambda functions are useful for short, throwaway functions that are used infrequently or as part of other expressions.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Map and Filter&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;filter&lt;/code&gt; functions are powerful tools for working with iterables, allowing concise manipulation and filtering of data.&lt;/p&gt;

&lt;p&gt;Let's say you have a list of strings and you want to convert each item of the list into uppercase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;fruits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apple&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;banana&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cherry&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;upper_case_loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;fruit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;upper_case_loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upper_case_loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can achieve the same using the &lt;code&gt;map&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;upper_case&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apple&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;banana&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cherry&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can utilize &lt;code&gt;map&lt;/code&gt; when you need to perform an operation on every element of an iterable. &lt;code&gt;filter&lt;/code&gt; is handy for selectively choosing elements based on a condition.&lt;/p&gt;

&lt;p&gt;You can learn more about the &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;reduce&lt;/code&gt; functions &lt;a href="https://blog.ashutoshkrris.in/mastering-lambdas-a-guide-to-anonymous-functions-in-python#heading-using-lambda-functions-as-arguments-in-higher-order-functions-map-filter-reduce" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Ternary Operator&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The ternary operator provides a condensed way to write conditional statements in a single line, enhancing code readability.&lt;/p&gt;

&lt;p&gt;Let's say, you have a number and you want to check if it's even or odd. You can do it using the traditional if condition as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Traditional if
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Even&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Odd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But you can achieve the same results in a single line using the ternary operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Ternary Operator
&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Even&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Odd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you need to assign values based on conditions, especially in situations requiring simple if-else checks, the ternary operator shines.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Zip Function&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;zip&lt;/code&gt; function enables you to combine multiple iterables element-wise, forming tuples of corresponding elements.&lt;/p&gt;

&lt;p&gt;Let's assume you have two lists: one containing the names of students and the other containing their respective grades for a specific assignment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Dilli&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Vikram&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Rolex&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Leo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;grades&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you want to create a report that pairs each student's name with their grade for easy comprehension or further analysis. You can do it by iterating over the list and appending them to a new list as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Dilli&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Vikram&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Rolex&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Leo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;grades&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;student_grade_pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;student_grade_pairs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;grades&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;student_grade_pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above loop method manually pairs elements from two lists by iterating through their indices, accessing elements at the same positions, and appending tuples of those elements into a new list &lt;code&gt;student_grade_pairs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But, what if I tell you that we can achieve the same pairing effect in one line using the &lt;code&gt;zip&lt;/code&gt; function as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Dilli&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Vikram&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Rolex&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Leo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;grades&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;student_grade_pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grades&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;student_grade_pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;zip&lt;/code&gt; function elegantly combines elements from both lists, creating pairs of corresponding elements as tuples. The result &lt;code&gt;student_grade_pairs&lt;/code&gt; is a list of tuples, where each tuple contains an element from the grades list paired with the corresponding element from the &lt;code&gt;students&lt;/code&gt; list.&lt;/p&gt;

&lt;p&gt;You can learn more about the &lt;code&gt;zip&lt;/code&gt; function &lt;a href="https://blog.ashutoshkrris.in/zipping-through-python-a-comprehensive-guide-to-the-zip-function" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Enumerate Function&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;enumerate&lt;/code&gt; function offers a concise way to iterate over a sequence while keeping track of the index.&lt;/p&gt;

&lt;p&gt;Let's say you're developing a feature where users can add items to their shopping list, and you want to display the items along with their position or index in the list for easy reference.&lt;/p&gt;

&lt;p&gt;You can do it using a traditional for-loop as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simulating a grocery list
&lt;/span&gt;&lt;span class="n"&gt;grocery_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Apples&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Milk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bread&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Eggs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cheese&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Displaying the grocery list with indices
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grocery_list&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;grocery_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The traditional loop with manual indexing involves using &lt;code&gt;range&lt;/code&gt; along with &lt;code&gt;len&lt;/code&gt; to generate indices that are then used to access elements in the &lt;code&gt;grocery_list&lt;/code&gt; list. This method requires more code and is less readable due to the explicit handling of indices.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;enumerate&lt;/code&gt; function simplifies the process by directly providing both indices and elements from the &lt;code&gt;grocery_list&lt;/code&gt; list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simulating a grocery list
&lt;/span&gt;&lt;span class="n"&gt;grocery_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Apples&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Milk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bread&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Eggs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cheese&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Displaying the grocery list with indices
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grocery_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's concise, readable, and more Pythonic, eliminating the need for manual index handling and making the code cleaner. This approach is generally preferred for its simplicity and clarity in obtaining indices and elements from an iterable.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;String Join&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;join&lt;/code&gt; method is a clean way to concatenate strings from an iterable into a single string.&lt;/p&gt;

&lt;p&gt;Suppose you have a list of words and want to create a sentence by joining these words using traditional concatenation. You'd do it as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using traditional concatenation
&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;awesome&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;powerful&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;sentence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;sentence&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;# Strip to remove the trailing space
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the traditional concatenation method, a loop iterates through the list of words, and each word is concatenated with a space. However, this approach requires creating a new string for each concatenation operation, which might not be efficient for larger strings due to string immutability.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;join&lt;/code&gt; method, on the other hand, is more efficient and concise. It joins the elements of the list using the specified separator (in this case, a space), creating the sentence in a single operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="c1"&gt;# Using join method
&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;awesome&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;powerful&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;sentence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method is generally the preferred way to join strings in Python due to its efficiency and readability.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Unpacking Lists&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Python's unpacking feature allows for efficient assignment of elements from iterables to variables.&lt;/p&gt;

&lt;p&gt;Suppose you have a list of numbers, and you want to assign each number to separate variables using traditional indexing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using traditional unpacking
&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the traditional unpacking method, individual elements from the list are accessed and assigned to separate variables by explicitly indexing each element. This method is more verbose and requires knowing the number of elements in advance.&lt;/p&gt;

&lt;p&gt;Now, let's accomplish the same using the &lt;code&gt;*&lt;/code&gt; operator for unpacking the list into variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using * operator for unpacking
&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can learn more about the &lt;code&gt;*&lt;/code&gt; operator and list unpacking in &lt;a href="https://blog.ashutoshkrris.in/mastering-list-destructuring-and-packing-in-python-a-comprehensive-guide#heading-destructuring-assignment" rel="noopener noreferrer"&gt;this tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Should You Always Use One-Liners?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While Python one-liners offer conciseness and elegance, there are considerations to keep in mind before applying them universally:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Readability&lt;/strong&gt; : One-liners might sacrifice readability for crispness. Complex one-liners can be hard to understand, especially for newcomers or when revisiting code after some time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maintainability&lt;/strong&gt; : Overusing one-liners, especially complex ones, can make code maintenance challenging. Debugging and modifying concise code might be more difficult.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt; : In certain scenarios, one-liners might not be the most performant solution. These concise expressions may consume more resources, such as memory or CPU, and their underlying operations might have higher time complexity, affecting efficiency, especially with large datasets or intensive computations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging&lt;/strong&gt; : Debugging a one-liner can be more challenging due to its compactness. Identifying issues or errors might take longer compared to well-structured, multiple-line code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt; : Not all situations warrant one-liners. Sometimes, a straightforward, explicit approach might be more suitable for code clarity, especially when working in teams.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ultimately, the decision to use one-liners should consider the trade-offs between conciseness and readability. Strive for a balance that enhances code clarity without compromising maintainability and understanding, especially when collaborating or working on larger projects.&lt;/p&gt;

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

&lt;p&gt;Mastering Python's concise techniques like list comprehensions, lambda functions, &lt;code&gt;enumerate&lt;/code&gt;, &lt;code&gt;join&lt;/code&gt;, &lt;code&gt;zip&lt;/code&gt;, and unpacking with the &lt;code&gt;*&lt;/code&gt; operator can significantly enhance code readability, efficiency, and simplicity. These methods offer elegant solutions to common programming challenges, reducing verbosity and improving code maintainability.&lt;/p&gt;

&lt;p&gt;Understanding when and how to use these Pythonic constructs empowers developers to write cleaner, more expressive code and enhance overall productivity in various programming scenarios.&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>A Beginner's Guide to Strategy Design Pattern</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Mon, 01 May 2023 08:36:13 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/a-beginners-guide-to-strategy-design-pattern-3be3</link>
      <guid>https://dev.to/ashutoshkrris/a-beginners-guide-to-strategy-design-pattern-3be3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The Strategy Design Pattern is a &lt;a href="https://shrinke.me/XNNXyxVS" rel="noopener noreferrer"&gt;behavioral design pattern&lt;/a&gt; that allows you to dynamically change the behavior of an object by encapsulating it into different strategies. This pattern enables an object to choose from multiple algorithms and behaviors at runtime, rather than statically choosing a single one.&lt;/p&gt;

&lt;p&gt;It is based on the principle of composition over inheritance. It defines a family of algorithms, encapsulates each one, and makes them interchangeable at runtime. The core idea behind this pattern is to separate the algorithms from the main object, allowing the object to delegate the algorithm's behavior to one of its contained strategies.&lt;/p&gt;

&lt;p&gt;In simpler terms, the Strategy Design Pattern provides a way to extract the behavior of an object into separate classes that can be swapped in and out at runtime. This enables the object to be more flexible and reusable, as different strategies can be easily added or modified without changing the object's core code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of using the Strategy Design Pattern
&lt;/h3&gt;

&lt;p&gt;Using the Strategy Design Pattern can provide several benefits, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved code flexibility&lt;/strong&gt; : By encapsulating the behavior of an object into different strategies, the code becomes more flexible and easier to modify.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Better code reusability&lt;/strong&gt; : Since the strategies are encapsulated and interchangeable, they can be reused across different objects and projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encourages better coding practices&lt;/strong&gt; : This pattern promotes good coding practices, such as separating concerns and reducing code complexity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplifies testing&lt;/strong&gt; : By separating the algorithms and behaviors from the object, testing becomes more straightforward.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Use cases for the Strategy Design Pattern
&lt;/h3&gt;

&lt;p&gt;The Strategy Design Pattern can be useful in various scenarios, such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sorting algorithms&lt;/strong&gt; : Different sorting algorithms can be encapsulated into separate strategies and passed to an object that needs sorting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validation rules&lt;/strong&gt; : Different validation rules can be encapsulated into separate strategies and passed to an object that needs validation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Text formatting&lt;/strong&gt; : Different formatting strategies can be encapsulated into separate strategies and passed to an object that needs formatting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database access&lt;/strong&gt; : Different database access strategies can be encapsulated into separate strategies and passed to an object that needs to access data from different sources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Payment strategy&lt;/strong&gt; : Different payment methods can be encapsulated into separate strategies and passed to an object that needs to process payments.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Understanding the Strategy Design Pattern
&lt;/h2&gt;

&lt;p&gt;The Strategy Design Pattern is a powerful pattern in the world of object-oriented programming. It provides a flexible way to encapsulate and swap the behavior of an object at runtime, enabling code to be more adaptable and easier to maintain. In this section, we will dive deeper into the Strategy Design Pattern, discussing its definition, components, and how it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components of the Strategy Design Pattern
&lt;/h3&gt;

&lt;p&gt;The Strategy Design Pattern consists of three primary components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt; : The object that will delegate its behavior to one of the contained strategies. The context maintains a reference to a strategy object and interacts with it through a common interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strategy Interface&lt;/strong&gt; : The interface that defines the behavior for all strategies. The strategies implement this interface to provide their unique implementation of the behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concrete Strategies&lt;/strong&gt; : The classes that implement the Strategy Interface. Each strategy encapsulates a specific behavior that the context can switch to at runtime.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How the Strategy Design Pattern Works
&lt;/h3&gt;

&lt;p&gt;The Strategy Design Pattern works by separating the behavior of an object from the object itself. The behavior is encapsulated into different strategies, each with its own implementation of the behavior. The context maintains a reference to a strategy object and interacts with it through a common interface. At runtime, the context can swap the current strategy with another one, effectively changing the object's behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of the Strategy Design Pattern in action
&lt;/h3&gt;

&lt;p&gt;One example of the Strategy Design Pattern in action is in a music streaming service where different subscription tiers have different pricing models. Each subscription tier could have a different pricing strategy that encapsulates its unique pricing logic. The service's billing system would delegate the pricing calculation to the current subscription's strategy, allowing for easy modification and extension of the pricing logic.&lt;/p&gt;

&lt;p&gt;Another example is the payment strategy. Different payment methods can be encapsulated into separate strategies, each with its own unique processing logic. A shopping cart application may use the Strategy Design Pattern to encapsulate credit card, PayPal, and cryptocurrency payment methods into separate strategies that can be swapped at runtime. The application's payment processing system would delegate the payment processing logic to the current payment method's strategy, allowing for easy modification and extension of the payment processing logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the Strategy Design Pattern
&lt;/h2&gt;

&lt;p&gt;In this section, we will discuss how to implement the Strategy Design Pattern. We will start with a code example that violates the Strategy Design Pattern and explain the problems with it. Then, we will refactor the code to demonstrate how to implement the Strategy Design Pattern.&lt;/p&gt;

&lt;p&gt;To implement the Strategy Design Pattern in Java, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Identify the algorithm or behavior that needs to be encapsulated and made interchangeable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define an interface that represents the behavior, with a single method signature that takes in any required parameters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement concrete classes that provide specific implementations of the behavior defined in the interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define a context class that holds a reference to the interface and calls its method when needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the context class to allow for the dynamic swapping of the concrete implementations at runtime.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Code Example
&lt;/h3&gt;

&lt;p&gt;Let's consider the following code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;withoutstrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PaymentType&lt;/span&gt; &lt;span class="n"&gt;paymentType&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;PaymentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CREDIT_CARD&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing credit card payment of amount "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;PaymentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEBIT_CARD&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing debit card payment of amount "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;PaymentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PAYPAL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing PayPal payment of amount "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid payment type"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setPaymentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentType&lt;/span&gt; &lt;span class="n"&gt;paymentType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paymentType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paymentType&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;PaymentType&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;CREDIT_CARD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;DEBIT_CARD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;PAYPAL&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, the &lt;code&gt;PaymentProcessor&lt;/code&gt; class has a &lt;code&gt;processPayment&lt;/code&gt; method that takes a payment amount and processes the payment. The payment type is set using the &lt;code&gt;setPaymentType&lt;/code&gt; method, which sets the &lt;code&gt;paymentType&lt;/code&gt; field. The &lt;code&gt;processPayment&lt;/code&gt; method then checks the value of &lt;code&gt;paymentType&lt;/code&gt; and processes the payment accordingly.&lt;/p&gt;

&lt;p&gt;The problem with this code is that it violates the &lt;a href="https://shrinke.me/b2Kl" rel="noopener noreferrer"&gt;Open-Closed Principle&lt;/a&gt;, which states that classes should be open for extension but closed for modification. In this code, if you want to add a new payment type, you would have to modify the &lt;code&gt;processPayment&lt;/code&gt; method, which violates the Open-Closed Principle.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;PaymentProcessor&lt;/code&gt; class violates the Strategy pattern by using conditional statements to determine the type of payment and then processing it accordingly. This approach can quickly become unmanageable and inflexible as the number of payment types increases.&lt;/p&gt;

&lt;p&gt;To fix this problem, you can use the Strategy Design Pattern. First, you define a common interface for all payment strategies, which in this case is the &lt;code&gt;PaymentStrategy&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;withstrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PaymentStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You then define concrete implementations of the &lt;code&gt;PaymentStrategy&lt;/code&gt; interface for each payment type. For example, here are the &lt;code&gt;CreditCardPaymentStrategy&lt;/code&gt;, &lt;code&gt;DebitCardPaymentStrategy&lt;/code&gt;, and &lt;code&gt;PaypalPaymentStrategy&lt;/code&gt; classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;withstrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreditCardPaymentStrategy&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing credit card payment of amount "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;withstrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DebitCardPaymentStrategy&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing debit card payment of amount "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;withstrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaypalPaymentStrategy&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing PayPal payment of amount "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you update the &lt;code&gt;PaymentProcessor&lt;/code&gt; class to take a &lt;code&gt;PaymentStrategy&lt;/code&gt; object in its constructor, which it uses to process the payment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;withstrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PaymentStrategy&lt;/span&gt; &lt;span class="n"&gt;paymentStrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentStrategy&lt;/span&gt; &lt;span class="n"&gt;paymentStrategy&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paymentStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paymentStrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;paymentStrategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation follows the Open-Closed Principle as well as Strategy Pattern because you can add new payment types by creating new implementations of the &lt;code&gt;PaymentStrategy&lt;/code&gt; interface without modifying the existing code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best practices for implementing the Strategy Design Pattern
&lt;/h3&gt;

&lt;p&gt;Here are a few best practices to keep in mind when implementing the Strategy Design Pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Keep the interface simple and focused on a single responsibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Encapsulate any stateful behavior in the concrete strategy classes, rather than in the context class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use dependency injection to pass the concrete strategy to the context class, rather than creating it directly in the context class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use an enum or a factory class to provide a centralized place for creating and managing concrete strategy objects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Real-world Applications of the Strategy Design Pattern
&lt;/h2&gt;

&lt;p&gt;The Strategy Design Pattern has been used extensively in various real-world applications. One such example is the &lt;strong&gt;Java Collections Framework&lt;/strong&gt;. The Collections Framework provides a set of interfaces and classes to represent collections of objects, such as lists, sets, and maps. The framework allows different strategies to be applied to collections based on their behavior.&lt;/p&gt;

&lt;p&gt;For instance, the Collections Framework includes a &lt;code&gt;sort()&lt;/code&gt; method that allows the sorting of collections. The &lt;code&gt;sort()&lt;/code&gt; method takes a Comparator object as an argument, which is responsible for comparing objects within the collection. The Comparator interface defines a strategy for comparing two objects, and the &lt;code&gt;sort()&lt;/code&gt; method uses this strategy to sort the collection.&lt;/p&gt;

&lt;p&gt;In addition, the Collections Framework also includes the Iterator interface, which defines a strategy for accessing elements of a collection. The Iterator allows the user to traverse the collection without exposing its internal structure, which can change over time. By using the Iterator interface, the user can switch between different strategies for accessing elements of the collection.&lt;/p&gt;

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

&lt;p&gt;In this tutorial, we have explored the Strategy Design Pattern and its implementation in Java. We have seen how the Strategy pattern can be used to separate the behavior of an object from its implementation, providing greater flexibility and maintainability in code.&lt;/p&gt;

&lt;p&gt;We discussed the components of the Strategy Design Pattern, including the Context, Strategy Interface, and Concrete Strategies. We also provided an example of how the pattern can be used to implement a payment system, allowing for multiple payment options to be implemented using a single interface.&lt;/p&gt;

&lt;p&gt;By separating the behavior of an object from its implementation, the Strategy pattern provides greater flexibility and adaptability to changing requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://shrinke.me/solid-principles" rel="noopener noreferrer"&gt;SOLID Principles for Better Software Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://shrinke.me/1ODLeXzl" rel="noopener noreferrer"&gt;Design Patterns: A Comprehensive Tutorial&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>designpattern</category>
      <category>java</category>
      <category>programming</category>
      <category>strategydesign</category>
    </item>
    <item>
      <title>Design Patterns: A Comprehensive Tutorial</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Mon, 01 May 2023 07:17:30 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/design-patterns-a-comprehensive-tutorial-3e3h</link>
      <guid>https://dev.to/ashutoshkrris/design-patterns-a-comprehensive-tutorial-3e3h</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Design patterns are proven solutions to commonly occurring software design problems. In other words, they are reusable templates that help to solve recurring design problems in software development. Design patterns were first introduced in the book &lt;a href="http://www.javier8a.com/itc/bd1/articulo.pdf" rel="noopener noreferrer"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt; by the &lt;em&gt;Gang of Four&lt;/em&gt; (Gamma, Helm, Johnson, and Vlissides) in 1994.&lt;/p&gt;

&lt;p&gt;Design patterns are essential in software development because they provide a common language and framework for communicating design ideas and solutions. They help developers to design robust, flexible, and maintainable software systems. Using design patterns ensures that the software is more reusable, testable, and scalable. Design patterns also promote code reuse and reduce the likelihood of errors and bugs in the software.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will explore different types of design patterns, their importance, and the benefits of using them in software development. We will also discuss how to choose the right design pattern for a particular situation and provide examples of design patterns used in real-world applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Design Patterns
&lt;/h2&gt;

&lt;p&gt;Design patterns are categorized into three main categories: &lt;strong&gt;Creational&lt;/strong&gt; , &lt;strong&gt;Structural&lt;/strong&gt; , and &lt;strong&gt;Behavioral&lt;/strong&gt; patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creational Design Patterns
&lt;/h3&gt;

&lt;p&gt;Creational patterns are concerned with object creation mechanisms, trying to create objects in a manner suitable to the situation. There are five types of creational patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Abstract Factory Pattern&lt;/strong&gt; : Provides an interface for creating families of related or dependent objects without specifying their concrete classes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Builder Pattern&lt;/strong&gt; : Separates the construction of a complex object from its representation, allowing the same construction process to create various representations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Factory Method Pattern&lt;/strong&gt; : Defines an interface for creating an object, but lets subclasses decide which class to instantiate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Object Pool Pattern&lt;/strong&gt; : Reuses and shares objects that are expensive to create.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prototype Pattern&lt;/strong&gt; : Creates new objects by copying an existing object, which serves as a prototype.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Singleton Pattern&lt;/strong&gt; : Ensures that a class has only one instance, and provides a global point of access to it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Structural Design Patterns
&lt;/h3&gt;

&lt;p&gt;Structural patterns deal with object composition to form larger structures and provide ways to realize relationships between objects. There are seven types of structural patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adapter Pattern&lt;/strong&gt; : Allows objects with incompatible interfaces to work together by creating an intermediary object that translates one interface to another.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bridge Pattern&lt;/strong&gt; : Decouples an abstraction from its implementation so that the two can vary independently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Composite Pattern&lt;/strong&gt; : Composes objects into tree structures to represent whole-part hierarchies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decorator Pattern&lt;/strong&gt; : Dynamically adds responsibilities to an object by wrapping it in an object of a decorator class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Facade Pattern&lt;/strong&gt; : Provides a unified interface to a set of interfaces in a subsystem, simplifying the interaction between the client and the subsystem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flyweight Pattern&lt;/strong&gt; : Uses sharing to support large numbers of fine-grained objects efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Private Class Data Pattern&lt;/strong&gt; : Restricts access to an object's data by encapsulating it within a separate object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Proxy Pattern&lt;/strong&gt; : Provides a surrogate or placeholder for another object to control access to it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Behavioral Design Patterns
&lt;/h3&gt;

&lt;p&gt;Behavioral patterns deal with communication between objects, focusing on how objects collaborate and fulfill responsibilities. There are eleven types of behavioral patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Chain of Responsibility Pattern&lt;/strong&gt; : Avoids coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Command Pattern&lt;/strong&gt; : Encapsulates a request as an object, allowing you to parameterize clients with different requests, queue or log requests, and support undoable operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interpreter Pattern&lt;/strong&gt; : Defines a grammatical representation of a language and provides an interpreter to parse sentences in the language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Iterator Pattern&lt;/strong&gt; : Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mediator Pattern&lt;/strong&gt; : Defines an object that encapsulates how a set of objects interact, promoting loose coupling by keeping objects from referring to each other explicitly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memento Pattern&lt;/strong&gt; : Captures and externalizes an object's internal state so that it can be restored later, without violating encapsulation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Null Object Pattern&lt;/strong&gt; : Provides a default value for an object, which can be used to avoid null checks in client code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Observer Pattern&lt;/strong&gt; : Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Pattern&lt;/strong&gt; : Allows an object to alter its behavior when its internal state changes so that it appears to change its class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strategy Pattern&lt;/strong&gt; : Defines a family of algorithms, encapsulates each one and makes them interchangeable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Template Method Pattern&lt;/strong&gt; : Defines the skeleton of an algorithm in a method, deferring some steps to subclasses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Visitor Pattern&lt;/strong&gt; : Separates an algorithm from an object structure by moving the hierarchy of methods into one object.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Choosing the Right Design Pattern
&lt;/h2&gt;

&lt;p&gt;Choosing the right design pattern for a particular situation requires a good understanding of the problem at hand and the available design patterns. It's important to choose a pattern that fits the problem, rather than trying to fit the problem into a preconceived pattern. When choosing a design pattern, there are several factors to consider, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity&lt;/strong&gt; : Consider the complexity of the problem and the proposed solution. Some patterns are simple and can be implemented quickly, while others are more complex and may require more time and resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt; : Consider the flexibility of the pattern and how well it will adapt to changes in the problem or requirements. Some patterns are more flexible than others and may be better suited to situations where requirements are likely to change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reusability&lt;/strong&gt; : Consider the reusability of the pattern and how it can be applied to other problems. Some patterns are more reusable than others and may be better suited to situations where similar problems are likely to occur.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Familiarity&lt;/strong&gt; : Consider the familiarity of the pattern and whether it is well-known and widely used. Choosing a well-known pattern can make it easier for other developers to understand and maintain the code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Examples of when to use certain design patterns include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Use the Singleton pattern when you need to ensure that only one instance of a class exists and it needs to be globally accessible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the Factory Method pattern when you need to create objects without specifying the exact class of object that will be created.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the Observer pattern when you need to notify a set of objects about changes to another object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the Strategy pattern when you need to dynamically change the behavior of an object at runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the Adapter pattern when you need to adapt the interface of an existing class to meet the needs of a new interface.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In summary, choosing the right design pattern requires careful consideration of the problem and the available patterns, taking into account factors such as complexity, flexibility, reusability, and familiarity. Choosing the right pattern can help simplify the code and make it easier to maintain over time.&lt;/p&gt;

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

&lt;p&gt;In this tutorial, we have covered the basics of design patterns, including the different types of patterns, how to choose the right pattern for a particular situation, and examples of when to use certain patterns.&lt;/p&gt;

&lt;p&gt;Key points to remember include the importance of understanding the problem at hand before choosing a design pattern, the need to consider factors such as complexity, flexibility, reusability, and familiarity when choosing a pattern, and the importance of using patterns to simplify code and make it easier to maintain.&lt;/p&gt;

&lt;p&gt;Overall, design patterns are an essential tool in any developer's toolkit. By using patterns effectively, developers can build more robust, maintainable, and scalable software systems that meet the needs of users and businesses alike. We recommend that developers continue to learn and explore design patterns to improve their skills and knowledge of software development.&lt;/p&gt;

</description>
      <category>java</category>
      <category>designpatterns</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>How To Download YouTube Playlist Using Python</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Sun, 30 Apr 2023 17:54:24 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/how-to-download-youtube-playlist-using-python-28gg</link>
      <guid>https://dev.to/ashutoshkrris/how-to-download-youtube-playlist-using-python-28gg</guid>
      <description>&lt;p&gt;YouTube is the world's largest video-sharing platform with millions of videos uploaded every day. Many times you come across a playlist of videos on YouTube that you want to watch offline or save for future reference. However, downloading a single video from YouTube is easy, but when it comes to downloading an entire playlist, it can be a daunting task. In such cases, automating the process using Python can save a lot of time and effort.&lt;/p&gt;

&lt;p&gt;In this tutorial, you will be using the Pytube library in Python to download entire YouTube playlists in various resolutions, including the high-quality 2160p resolution. Pytube is a lightweight library that allows easy access to YouTube videos and metadata. With Pytube, we can easily extract video URLs, download videos, and even extract audio from videos. So, let's dive into the tutorial and learn how to download a YouTube playlist using Python.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're in a hurry, jump to the &lt;a href="https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50" rel="noopener noreferrer"&gt;GitHub gist&lt;/a&gt; to get the code immediately.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, you should have a basic understanding of Python programming language, including installing Python packages using pip.&lt;/p&gt;

&lt;p&gt;You will also need to install the Pytube library, which can be installed using pip. Open a command prompt or terminal window and type the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pytube
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Apart from Python and Pytube, you will also need to have FFmpeg installed on your system. FFmpeg is a command-line tool used for handling multimedia files. It is required for Pytube to be able to download videos in various resolutions. You can download FFmpeg from the &lt;a href="https://www.ffmpeg.org/download.html" rel="noopener noreferrer"&gt;official website&lt;/a&gt; and follow the installation instructions for your operating system.&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's Code It!
&lt;/h2&gt;

&lt;p&gt;Roll up your sleeves, fire up your favorite code editor, and let's get started!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlbn3254mlmh8mscy2ah.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlbn3254mlmh8mscy2ah.gif" alt="Cat Coder Gif" width="300" height="300"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Import the Libraries
&lt;/h3&gt;

&lt;p&gt;Let's import the necessary libraries for the program to run correctly.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pytube&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Playlist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;YouTube&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The code imports the &lt;code&gt;os&lt;/code&gt; module to handle operating system functionalities, &lt;code&gt;re&lt;/code&gt; module to handle regular expressions, and &lt;code&gt;pytube&lt;/code&gt; module to download the YouTube playlist.&lt;/p&gt;
&lt;h3&gt;
  
  
  Create the Function
&lt;/h3&gt;

&lt;p&gt;Let's define a function called &lt;code&gt;download_playlist&lt;/code&gt;. The function takes two parameters; the playlist URL and the desired video resolution.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;download_playlist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;playlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Playlist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;playlist_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\W+&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It first creates a new &lt;code&gt;Playlist&lt;/code&gt; object using the Pytube library and extracts the name of the playlist. It then checks if a folder with the same name exists in the current working directory. If not, it creates a new folder with the playlist name.&lt;/p&gt;

&lt;p&gt;Note that the &lt;code&gt;re.sub()&lt;/code&gt; function replaces any non-alphanumeric characters in the playlist title with a hyphen ("-") character. We do so because folder and file names in most file systems have restrictions on the characters they can contain.&lt;/p&gt;
&lt;h3&gt;
  
  
  Downloading the Videos
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Playlist&lt;/code&gt; object provides a &lt;code&gt;videos&lt;/code&gt; property which is an iterable of &lt;code&gt;YouTube&lt;/code&gt; objects. You first iterate through the list of videos in the playlist using a &lt;code&gt;for&lt;/code&gt; loop and &lt;code&gt;enumerate&lt;/code&gt; function.:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;start&lt;/code&gt; parameter set to 1 to start counting from 1 instead of 0 because you're going to use the index in the filenames. Thus it makes sense to start from 1.&lt;/p&gt;

&lt;p&gt;Next, create a &lt;code&gt;YouTube&lt;/code&gt; object for each video using its watch URL, and specify to use OAuth for authentication:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;YouTube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;watch_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_oauth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Recently, there were several issues where PyTube was throwing a KeyError. The fix was to use the &lt;code&gt;use_oauth=True&lt;/code&gt; parameter. When you run the code for the first time, it will ask you to login into your YouTube account.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Filter the available video streams to select the one with the desired resolution, and get its filename:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;YouTube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;watch_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_oauth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;video_resolution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;video_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_resolution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Determine the full path and filename for the video file, and check if it already exists. If it does, skip downloading this video and move on to the next one:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;YouTube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;watch_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_oauth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;video_resolution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;video_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_resolution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;video_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;video_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; already exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the desired resolution is not available, download the video with the highest resolution instead:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;video_streams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;video_streams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;highest_resolution_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_highest_resolution&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;video_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highest_resolution_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_filename&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Downloading &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;highest_resolution_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;highest_resolution_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;video_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the desired resolution is available, you don't have to download it directly. If you do so, the downloaded video won't have sound. Instead, download both the video and audio streams separately, and merge them using the FFmpeg library to create the final video file. Finally, rename the merged file and delete the temporary video and audio files:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;video_streams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;video_streams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;video_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video_streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;video_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_filename&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Downloading video for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;video_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;video.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;audio_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_audio_only&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Downloading audio for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;audio_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audio.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ffmpeg -y -i video.mp4 -i audio.mp4 -c:v copy -c:a aac final.mp4 -loglevel quiet -stats&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;video.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audio.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The video stream is initially downloaded as &lt;code&gt;video.mp4&lt;/code&gt; and the audio stream is downloaded as &lt;code&gt;audio.mp4&lt;/code&gt;. Next, the &lt;code&gt;ffmpeg&lt;/code&gt; command takes two input files (&lt;code&gt;video.mp4&lt;/code&gt; and &lt;code&gt;audio.mp4&lt;/code&gt;), copies the video codec from the input file and uses the AAC codec for audio, and saves the output as &lt;code&gt;final.mp4&lt;/code&gt;. The output file is created by merging the video and audio streams from the two input files.&lt;/p&gt;

&lt;p&gt;After &lt;code&gt;ffmpeg&lt;/code&gt; finishes processing, the &lt;code&gt;final.mp4&lt;/code&gt; is renamed &lt;code&gt;video_path&lt;/code&gt; and the video and audio stream files are deleted.&lt;/p&gt;
&lt;h3&gt;
  
  
  The &lt;code&gt;download_playlist&lt;/code&gt; Function
&lt;/h3&gt;

&lt;p&gt;At this point, you have completed the &lt;code&gt;download_playlist&lt;/code&gt; function. It should look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;download_playlist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;playlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Playlist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;playlist_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\W+&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;YouTube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;watch_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_oauth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;video_resolution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;video_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_resolution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;video_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;video_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; already exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;video_streams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;video_streams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;highest_resolution_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_highest_resolution&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;video_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highest_resolution_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_filename&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Downloading &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;highest_resolution_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;highest_resolution_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;video_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;video_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video_streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;video_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_filename&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Downloading video for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;video_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;video.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;audio_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_audio_only&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Downloading audio for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;audio_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audio.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ffmpeg -y -i video.mp4 -i audio.mp4 -c:v copy -c:a aac final.mp4 -loglevel quiet -stats&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;video.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audio.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;----------------------------------&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A line of dashes is also printed after every iteration to separate each video as they are downloaded.&lt;/p&gt;
&lt;h3&gt;
  
  
  Main Function
&lt;/h3&gt;

&lt;p&gt;Let's create the main function that takes input from the user for the playlist URL and desired video resolution. It then calls the &lt;code&gt;download_playlist&lt;/code&gt; function with the user's inputs.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;playlist_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter the playlist url: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;resolutions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;240p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;360p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;480p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;720p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1080p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1440p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2160p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resolution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Please select a resolution &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;resolutions&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;download_playlist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playlist_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Completed Code
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you learned how you can use PyTube and FFmpeg libraries to download videos from a YouTube playlist in high resolutions such as 1080p, 1440p, and even 2160p.&lt;/p&gt;

&lt;p&gt;I hope you found the tutorial helpful. If so, don't forget to star the &lt;a href="https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50" rel="noopener noreferrer"&gt;GitHub gist&lt;/a&gt; and share this tutorial with others.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The code has been tested with Pytube 12.1.3. It may not work properly at a later point in time.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>automation</category>
    </item>
    <item>
      <title>SOLID Principles for Better Software Design</title>
      <dc:creator>Ashutosh Krishna</dc:creator>
      <pubDate>Sat, 29 Apr 2023 19:27:04 +0000</pubDate>
      <link>https://dev.to/ashutoshkrris/solid-principles-for-better-software-design-3e16</link>
      <guid>https://dev.to/ashutoshkrris/solid-principles-for-better-software-design-3e16</guid>
      <description>&lt;p&gt;SOLID principles are a set of guidelines for writing high-quality, maintainable, and scalable software. They were introduced by Robert C. Martin, a renowned software engineer, and consultant, in his 2000 paper &lt;a href="https://fi.ort.edu.uy/innovaportal/file/2032/1/design_principles.pdf" rel="noopener noreferrer"&gt;Design Principles and Design Patterns&lt;/a&gt; to help developers write software that is easy to understand, modify, and extend. These concepts were later built upon by Michael Feathers, who introduced us to the SOLID acronym.&lt;/p&gt;

&lt;p&gt;The SOLID acronym stands for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;S&lt;/strong&gt;ingle Responsibility Principle (SRP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;O&lt;/strong&gt;pen-Closed Principle (OCP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;L&lt;/strong&gt;iskov Substitution Principle (LSP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;I&lt;/strong&gt;nterface Segregation Principle (ISP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;D&lt;/strong&gt;ependency Inversion Principle (DIP)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These principles provide a way for developers to organize their code and create software that is flexible, easy to change, and testable. Applying SOLID principles can lead to code that is more modular, maintainable, and extensible, and it can make it easier for developers to work collaboratively on a codebase.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will explore each of the SOLID principles in detail, explain why they are important, and provide examples of how they can be applied in practice. By the end of this tutorial, you should have a good understanding of the SOLID principles and how to apply them to your software development projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single Responsibility Principle
&lt;/h2&gt;

&lt;p&gt;The Single Responsibility Principle (SRP) states that &lt;strong&gt;a class should have only one reason to change&lt;/strong&gt; , or in other words, &lt;strong&gt;it should have only one responsibility&lt;/strong&gt;. This means that a class should have only one job to do, and it should do it well.&lt;/p&gt;

&lt;p&gt;If a class has too many responsibilities, it can become hard to understand, maintain, and modify. Changes to one responsibility can inadvertently affect another responsibility, leading to unintended consequences and bugs. By following SRP, we can create code that is more modular, easier to understand, and less prone to errors.&lt;/p&gt;

&lt;p&gt;Let's take an example that violates the SRP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Marker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Marker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code defines a simple &lt;code&gt;Marker&lt;/code&gt; class having three instance variables - &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt; and &lt;code&gt;price&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Marker&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Invoice&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Marker&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;calculateTotal&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;printInvoice&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// printing implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveToDb&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// save to database implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above &lt;code&gt;Invoice&lt;/code&gt; class violates SRP because it has multiple responsibilities - it is responsible for calculating the total amount, printing the invoice, and saving the invoice to the database. As a result, if the calculation logic changes, such as the addition of taxes, the &lt;code&gt;calculateTotal()&lt;/code&gt; method would require modification. Similarly, if the printing or database-saving implementation changes at any point, the class would need to be changed. Therefore, there are several reasons for the class to be modified, which could lead to increased maintenance costs and complexity.&lt;/p&gt;

&lt;p&gt;Here's how you can modify the code to follow SRP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Marker&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Invoice&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Marker&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;calculateTotal&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceDao&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;InvoiceDao&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveToDb&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// save to database implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoicePrinter&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;InvoicePrinter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;printInvoice&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// printing implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this refactored example, we have split the responsibilities of the &lt;code&gt;Invoice&lt;/code&gt; class into three separate classes - &lt;code&gt;Invoice&lt;/code&gt;, &lt;code&gt;InvoiceDao&lt;/code&gt;, and &lt;code&gt;InvoicePrinter&lt;/code&gt;. The &lt;code&gt;Invoice&lt;/code&gt; class is responsible only for calculating the total amount, and the printing and saving responsibilities have been delegated to separate classes. This makes the code more modular, easier to understand, and less prone to errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open-Closed Principle
&lt;/h2&gt;

&lt;p&gt;The Open-Closed Principle (OCP) states that &lt;strong&gt;software entities (classes, modules, functions, etc.) should be open for extension but closed for modification&lt;/strong&gt;. This means that the behavior of a software entity can be extended without modifying its source code.&lt;/p&gt;

&lt;p&gt;The OCP is essential because it promotes software extensibility and maintainability. By allowing software entities to be extended without modification, developers can add new functionality without the risk of breaking existing code. This results in code that is easier to maintain, extend, and reuse.&lt;/p&gt;

&lt;p&gt;Let's take the previous example again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceDao&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;InvoiceDao&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveToDb&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// save to database implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;InvoiceDao&lt;/code&gt; class has a single responsibility of saving the invoice to the database. But, suppose there's a new requirement to save the invoice to a file as well. One way to implement this requirement would be to modify the existing &lt;code&gt;InvoiceDao&lt;/code&gt; class by adding a &lt;code&gt;saveToFile()&lt;/code&gt; method. However, this violates the Open-Closed Principle because it modifies the existing code that has already been tested and is live in production.&lt;/p&gt;

&lt;p&gt;To follow the OCP, a better solution would be to create an &lt;code&gt;InvoiceDao&lt;/code&gt; interface and implement it separately for database and file saving as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;InvoiceDao&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseInvoiceDao&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;InvoiceDao&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// save to database implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileInvoiceDao&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;InvoiceDao&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// save to file implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, if there's a new requirement to save the invoice to another data store, you can implement a new &lt;code&gt;InvoiceDao&lt;/code&gt; implementation without modifying the existing code. Thus, the &lt;code&gt;InvoiceDao&lt;/code&gt; interface is open for extension and closed for modification, which follows the OCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Liskov Substitution Principle
&lt;/h2&gt;

&lt;p&gt;The Liskov Substitution Principle (LSP) states that &lt;strong&gt;any instance of a derived class should be substitutable for an instance of its base class without affecting the correctness of the program&lt;/strong&gt;. In other words, a derived class should behave like its base class in all contexts. In more simple terms, if class A is a subtype of class B, you should be able to replace B with A without breaking the behavior of your program.&lt;/p&gt;

&lt;p&gt;The importance of LSP lies in its ability to ensure that the behavior of a program remains consistent and predictable when substituting objects of different classes. Violating LSP can lead to unexpected behavior, bugs, and maintainability issues.&lt;/p&gt;

&lt;p&gt;Let's take an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnOnEngine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the given example, the interface &lt;code&gt;Bike&lt;/code&gt; has two methods, &lt;code&gt;turnOnEngine()&lt;/code&gt; and &lt;code&gt;accelerate()&lt;/code&gt;. Two classes implement this interface, &lt;code&gt;Motorbike&lt;/code&gt; and &lt;code&gt;Bicycle&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Motorbike&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isEngineOn&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnOnEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;isEngineOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Motorbike&lt;/code&gt; correctly implements the &lt;code&gt;turnOnEngine()&lt;/code&gt; method, as it sets the &lt;code&gt;isEngineOn&lt;/code&gt; boolean to true. It also correctly implements the &lt;code&gt;accelerate()&lt;/code&gt; method by increasing the &lt;code&gt;speed&lt;/code&gt; by 5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bicycle&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isEngineOn&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;turnOnEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AssertionError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"There is no engine!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accelerate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the &lt;code&gt;Bicycle&lt;/code&gt; class throws an &lt;code&gt;AssertionError&lt;/code&gt; in the &lt;code&gt;turnOnEngine()&lt;/code&gt; method because it has no engine. This means that an instance of &lt;code&gt;Bicycle&lt;/code&gt; cannot be substituted for an instance of &lt;code&gt;Bike&lt;/code&gt; without breaking the behavior of the program.&lt;/p&gt;

&lt;p&gt;In other words, if the &lt;code&gt;Bicycle&lt;/code&gt; class is considered a subtype of the &lt;code&gt;Bike&lt;/code&gt; interface, then according to LSP, any instance of &lt;code&gt;Bike&lt;/code&gt; should be replaceable with an instance of &lt;code&gt;Bicycle&lt;/code&gt; without altering the correctness of the program. But in this case, it's not true because &lt;code&gt;Bicycle&lt;/code&gt; throws an &lt;code&gt;AssertionError&lt;/code&gt; while trying to turn on the engine. Therefore, the code violates the LSP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interface Segregation Principle
&lt;/h2&gt;

&lt;p&gt;The Interface Segregation Principle (ISP) focuses on designing interfaces that are specific to their client's needs. It states that no client should be forced to depend on methods it does not use.&lt;/p&gt;

&lt;p&gt;The principle suggests that &lt;strong&gt;instead of creating a large interface that covers all the possible methods, it's better to create smaller, more focused interfaces for specific use cases&lt;/strong&gt;. This approach results in interfaces that are more cohesive and less coupled.&lt;/p&gt;

&lt;p&gt;Consider a &lt;code&gt;Vehicle&lt;/code&gt; interface as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;startEngine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stopEngine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;drive&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then you have a class called &lt;code&gt;Car&lt;/code&gt; that implements the &lt;code&gt;Vehicle&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;startEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stopEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;drive&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UnsupportedOperationException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This vehicle cannot fly."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;Vehicle&lt;/code&gt; interface has too many methods. The &lt;code&gt;Car&lt;/code&gt; class is forced to implement all of them, even though they cannot fly. This violates the ISP because the &lt;code&gt;Vehicle&lt;/code&gt; interface is not properly segregated into smaller interfaces based on related functionality.&lt;/p&gt;

&lt;p&gt;Let's understand how you can follow ISP here. Suppose you refactor the &lt;code&gt;Vehicle&lt;/code&gt; interface into smaller, more focused interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;startEngine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stopEngine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;drive&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Flyable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can have a class called &lt;code&gt;Car&lt;/code&gt; that only implements the &lt;code&gt;Drivable&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Drivable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;startEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stopEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;drive&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, thanks to interface segregation, you can have another class called &lt;code&gt;Airplane&lt;/code&gt; that implements both the &lt;code&gt;Drivable&lt;/code&gt; and &lt;code&gt;Flyable&lt;/code&gt; interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Airplane&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Drivable&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Flyable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;startEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stopEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;drive&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implementation&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, you have properly segregated the &lt;code&gt;Vehicle&lt;/code&gt; interface into smaller interfaces based on related functionality. This adheres to the ISP and makes your code more flexible and maintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency Inversion Principle
&lt;/h2&gt;

&lt;p&gt;The Dependency Inversion Principle (DIP) states that &lt;strong&gt;high-level modules should not depend on low-level modules, but both should depend on abstractions&lt;/strong&gt;. Abstractions should not depend on details; details should depend on abstractions. This principle aims to reduce coupling between modules, increase modularity, and make the code easier to maintain, test, and extend.&lt;/p&gt;

&lt;p&gt;For example, consider a scenario where you have a class that needs to use an instance of another class. In the traditional approach, the first class would directly create an instance of the second class, leading to a tight coupling between them. This makes it difficult to change the implementation of the second class or to test the first class independently. However, if you apply the DIP, the first class would depend on an abstraction of the second class instead of the implementation, making it possible to easily change the implementation and test the first class independently.&lt;/p&gt;

&lt;p&gt;Here is an example that violates the DIP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherTracker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;currentConditions&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Emailer&lt;/span&gt; &lt;span class="n"&gt;emailer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;WeatherTracker&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;emailer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Emailer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setCurrentConditions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentConditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weatherDescription&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"rainy"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;emailer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"It is rainy"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Emailer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Email sent: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;WeatherTracker&lt;/code&gt; class directly creates an instance of the &lt;code&gt;Emailer&lt;/code&gt; class, making it tightly coupled to the implementation. This makes it difficult to change the implementation of the &lt;code&gt;Emailer&lt;/code&gt; class or to test the &lt;code&gt;WeatherTracker&lt;/code&gt; class independently.&lt;/p&gt;

&lt;p&gt;Here is an example of how to apply the DIP to the above code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Notifier&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;alertWeatherConditions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherTracker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;currentConditions&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Notifier&lt;/span&gt; &lt;span class="n"&gt;notifier&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;WeatherTracker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Notifier&lt;/span&gt; &lt;span class="n"&gt;notifier&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notifier&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setCurrentConditions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentConditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weatherDescription&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"rainy"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;notifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;alertWeatherConditions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"It is rainy"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Emailer&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Notifier&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;alertWeatherConditions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Email sent: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SMS&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Notifier&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;alertWeatherConditions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SMS sent: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;weatherDescription&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, you created a &lt;code&gt;Notifier&lt;/code&gt; interface that defines the &lt;code&gt;alertWeatherConditions&lt;/code&gt; method. The &lt;code&gt;WeatherTracker&lt;/code&gt; class now depends on this interface instead of the &lt;code&gt;Emailer&lt;/code&gt; class, making it possible to easily change the implementation and test the &lt;code&gt;WeatherTracker&lt;/code&gt; class independently. You also created two implementations of the &lt;code&gt;Notifier&lt;/code&gt; interface, &lt;code&gt;Emailer&lt;/code&gt;, and &lt;code&gt;SMS&lt;/code&gt;, to demonstrate how you can change the implementation of the &lt;code&gt;WeatherTracker&lt;/code&gt; class without affecting its behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, you learned about SOLID principles which is a very important part of Design Principles. By applying these principles in your software development projects, you can create code that is easier to maintain, extend, and modify, leading to more robust, flexible, and reusable software. This will also lead to better collaboration among team members, as the code becomes more modular and easier to work with.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>programming</category>
      <category>java</category>
      <category>solidprinciples</category>
    </item>
  </channel>
</rss>
