<?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: Jay D</title>
    <description>The latest articles on DEV Community by Jay D (@jay_d_530f1ef9b9e9217036a).</description>
    <link>https://dev.to/jay_d_530f1ef9b9e9217036a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2610321%2F6d0df740-2fa5-4c79-a811-1adf02145c20.png</url>
      <title>DEV Community: Jay D</title>
      <link>https://dev.to/jay_d_530f1ef9b9e9217036a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jay_d_530f1ef9b9e9217036a"/>
    <language>en</language>
    <item>
      <title>Building Immutable Classes in Java: A Developer’s Guide with a Real-Life Example</title>
      <dc:creator>Jay D</dc:creator>
      <pubDate>Thu, 26 Dec 2024 15:04:40 +0000</pubDate>
      <link>https://dev.to/jay_d_530f1ef9b9e9217036a/building-immutable-classes-in-java-a-developers-guide-with-a-real-life-example-13m3</link>
      <guid>https://dev.to/jay_d_530f1ef9b9e9217036a/building-immutable-classes-in-java-a-developers-guide-with-a-real-life-example-13m3</guid>
      <description>&lt;p&gt;You’ve probably heard about immutable classes. But have you ever wondered why they’re so important and how to build your own custom immutable class? In this, we’ll explore immutability in Java with a real-life user profile example to help you understand and apply this concept effectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Is an Immutable Class?&lt;/strong&gt;&lt;br&gt;
An immutable class is a class whose instances cannot be modified after they are created. Once you create an object, its state stays the same forever.&lt;/p&gt;

&lt;p&gt;In Java, popular examples of immutable classes include String, Integer, and other wrapper classes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Are Immutable Classes Useful?&lt;/strong&gt;&lt;br&gt;
    1.&lt;strong&gt;Thread-Safety&lt;/strong&gt;: Since immutable objects can’t be changed, they’re naturally thread-safe. No synchronization is required.&lt;br&gt;
    2.&lt;strong&gt;Ease of Use&lt;/strong&gt;: Immutable objects are simple to use and share across methods or threads without worrying about unexpected changes.&lt;br&gt;
    3.&lt;strong&gt;Predictable Behavior&lt;/strong&gt;: You know the state of an immutable object will never change, which makes debugging easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-World Example: Immutable User Profile&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a user profile in an application. When a user creates a profile, their username, email, and date of birth are fixed. If they need to update any detail (e.g., change their email), the system creates a new profile instead of modifying the existing one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementing an Immutable User Class&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import java.util.Date;

public final class User {
    private final String username;
    private final String email;
    private final Date dateOfBirth;

    // Constructor to initialize all fields
    public User(String username, String email, Date dateOfBirth) {
        this.username = username;
        this.email = email;
        // Defensively copy mutable fields like Date
        this.dateOfBirth = new Date(dateOfBirth.getTime());
    }

    // Getter for username
    public String getUsername() {
        return username;
    }

    // Getter for email
    public String getEmail() {
        return email;
    }

    // Getter for date of birth (return a copy of the date to ensure immutability)
    public Date getDateOfBirth() {
        return new Date(dateOfBirth.getTime());
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", email='" + email + '\'' +
                ", dateOfBirth=" + dateOfBirth +
                '}';
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Is This Class Immutable?&lt;/strong&gt;&lt;br&gt;
    1.final Class: The User class is declared as final, so no subclass can modify its behavior.&lt;br&gt;
    2.Private, Final Fields: All fields (username, email, and dateOfBirth) are private and final, ensuring they are initialized only once.&lt;br&gt;
    3.No Setters: The class does not have any setter methods to modify its fields.&lt;br&gt;
    4.Defensive Copying: The Date field is mutable, so:&lt;br&gt;
    • A new Date object is created in the constructor.&lt;br&gt;
    • A copy of the Date is returned in the getter to protect the original object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using the Immutable User Class&lt;/strong&gt;&lt;br&gt;
Here’s how you can use the User class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.Date;

public class Main {
    public static void main(String[] args) {
        // Create a new User object
        Date dob = new Date();
        User user = new User("sachin_test", "sachin@gmail.com", dob);

        // Print the user details
        System.out.println("Original User: " + user);

        // Attempt to modify the date of birth
        dob.setTime(0); // Changing the original Date object
        System.out.println("After Modifying Original Date: " + user);

        // Try modifying the returned date from getter
        Date retrievedDate = user.getDateOfBirth();
        retrievedDate.setTime(0); // Changing the retrieved Date object
        System.out.println("After Modifying Retrieved Date: " + user);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;Original User: User{username='sachin_test',email='&lt;a href="mailto:sachin@gmail.com"&gt;sachin@gmail.com&lt;/a&gt;', dateOfBirth=Tue Dec 24 00:00:00 IST 2024}&lt;br&gt;
After Modifying Original Date: User{username='sachin_test', email='&lt;a href="mailto:sachin@gmail.com"&gt;sachin@gmail.com&lt;/a&gt;', dateOfBirth=Tue Dec 24 00:00:00 IST 2024}&lt;br&gt;
After Modifying Retrieved Date: User{username='sachin_test', email='&lt;a href="mailto:sachin@gmail.com"&gt;sachin@gmail.com&lt;/a&gt;', dateOfBirth=Tue Dec 24 00:00:00 IST 2024}&lt;/p&gt;

&lt;p&gt;As you can see, the User object remains unchanged, proving its immutability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Defensive Copying Matters&lt;/strong&gt;&lt;br&gt;
Without defensive copying, the immutability of the class can be compromised. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public User(String username, String email, Date dateOfBirth) {
    this.username = username;
    this.email = email;
    // If we don't copy the date, external changes to the original Date object will affect our class
    this.dateOfBirth = dateOfBirth;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would allow changes to the Date object outside the class to affect the User object’s state. Defensive copying prevents this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of Immutable User Class&lt;/strong&gt;&lt;br&gt;
    1.Data Safety: The user profile data cannot be altered unintentionally.&lt;br&gt;
    2.Thread Safety: The User object can be safely shared between multiple threads.&lt;br&gt;
    3.Simplified Debugging: No need to trace how the state of the object changes over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-Life Applications of Immutable Classes&lt;/strong&gt;&lt;br&gt;
    1.APIs: Immutable classes are widely used in APIs where data integrity is crucial. For example, HttpRequest and HttpResponse objects in web frameworks often use immutability.&lt;br&gt;
    2.Multithreading: Immutable objects eliminate synchronization issues in multithreaded environments.&lt;br&gt;
    3.Data Modeling: Immutable classes are ideal for representing fixed data, like user profiles, currency, or coordinates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Creating immutable classes in Java is a powerful way to design reliable, thread-safe, and maintainable code. By following the principles of immutability, you can ensure the integrity of your objects and prevent unintended side effects.&lt;/p&gt;

&lt;p&gt;The User example above demonstrates how to implement an immutable class while addressing potential pitfalls like mutable fields. Now it’s your turn—try creating your own immutable classes and see how they make your code cleaner and safer!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Single Responsibility Principle in Java</title>
      <dc:creator>Jay D</dc:creator>
      <pubDate>Tue, 24 Dec 2024 14:51:16 +0000</pubDate>
      <link>https://dev.to/jay_d_530f1ef9b9e9217036a/single-responsibility-principle-in-java-2l51</link>
      <guid>https://dev.to/jay_d_530f1ef9b9e9217036a/single-responsibility-principle-in-java-2l51</guid>
      <description>&lt;p&gt;Hey there! When you're just starting out with coding, it's easy to write code that works but is hard to read or change later. that's where SOLID Principles come in ! They are like rules to help you write clean and maintainable code.&lt;br&gt;
Imagine we're building a ride sharing app(like Uber)&lt;/p&gt;

&lt;p&gt;What Does &lt;strong&gt;SOLID&lt;/strong&gt; Stand for?&lt;br&gt;
&lt;strong&gt;S:&lt;/strong&gt; Single Responsibility Principal&lt;br&gt;
&lt;strong&gt;O:&lt;/strong&gt; Open/Closed Principle&lt;br&gt;
&lt;strong&gt;L:&lt;/strong&gt; Liskov Substitution Principle&lt;br&gt;
&lt;strong&gt;I:&lt;/strong&gt; Interface Segregation Principle&lt;br&gt;
&lt;strong&gt;D:&lt;/strong&gt; Dependency Inversion Principle&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Single Responsibility Principal (SRP)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; One Class Should do only one job&lt;br&gt;
&lt;strong&gt;Problem:&lt;/strong&gt; The Overloaded Class&lt;br&gt;
Imagine a class in your ride-sharing app that handles booking rides, payments and rating drivers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class RideService {
       void bookRide(){/* Logic for booking ride */}
       void processPayment(){/* Logic for process payment */}
       void rateDriver(){/* Logic for reviews */}
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your payment system changes, you risk  breaking the ride-booking code.&lt;br&gt;
That's bad!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Divide the work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class RideBooking {
   void bookRide(){/* Only handles booking ride */}
}

class PaymentService{
   void processPayment(){/* Only handles payment process */}
}

class DriverRating{
  void rateDriver(){/* Only handle reviews */}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, If something goes wrong with payments, it won't mess up ride booking.&lt;br&gt;
Everyone sticks to their job!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Open/Closed Principle&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Rule:&lt;/strong&gt; Classes should be open for extension but closed for modification &lt;br&gt;
&lt;strong&gt;Problem:&lt;/strong&gt; Your payment system initially supports only Credit card payments. Adding support for PayPal requires modifying existing code, which could introduce bugs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class PaymentProcesser{
      double processPayments(String type){
          if(type.equals("CrediCard")){
             return 90.0;          
         }else if (type.equals("PayPal")){
             return 90.0;
        }
       return 0.0;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;  Use an interface to  make the system extensible without modifying existing code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface PaymenTMetod{
   double processPayment();
}

class CrediCardPayment implements PaymentMethod{
     public double processPayment() { return 90.0; }
}

class PayPalPayment implements PaymentMethod{
     public double processPayment() { return 95.0; }
}

class PaymentProcessor{
     double process(PaymentMethod payment){
        return payment.processPayment();
     }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Liskov Substitution Principle&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Rule:&lt;/strong&gt; If something works with a parent class, &lt;br&gt;
it should also work with its child classes&lt;br&gt;
&lt;strong&gt;Problem:&lt;/strong&gt; Unpredictable Vehicles&lt;br&gt;
Your app allows people to book cars, bikes, or trucks. &lt;br&gt;
But one day, someone tries to book a truck for a ride, &lt;br&gt;
and the app crashes. &lt;br&gt;
Why? Because trucks aren’t supposed to take passengers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Vehicle {
    void startRide() { System.out.println("Ride started"); }
}

class Truck extends Vehicle {
    @Override
    void startRide() {
        throw new UnsupportedOperationException("Trucks can't be booked");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you use Truck like any other vehicle, it doesn’t work as expected.&lt;/p&gt;

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

&lt;p&gt;Let’s ensure that every type of Vehicle behaves as it should.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class Vehicle {
    abstract void startRide();
}

class Car extends Vehicle {
    void startRide() { System.out.println("Car ride started"); }
}

class Bike extends Vehicle {
    void startRide() { System.out.println("Bike ride started"); }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, only vehicles that can take rides are part of the system. Everyone plays fair!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Interface Segregation Principle&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Rule:&lt;/strong&gt; A class should not be forced to implement methods that doesnt use.&lt;br&gt;
&lt;strong&gt;Problem:&lt;/strong&gt; Too Many Responsibilities&lt;br&gt;
Drivers in your app can accept rides and see earnings, &lt;br&gt;
while admins can manage drivers. &lt;br&gt;
If you give both the same interface, it looks 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;interface AppUser {
    void acceptRide();
    void viewEarnings();
    void manageDrivers();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drivers don’t manage drivers, &lt;br&gt;
so they leave that method empty or throw an error. That’s awkward!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Keep Interfaces Small&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface RideHandler {
    void acceptRide();
}

interface EarningsViewer {
    void viewEarnings();
}

interface DriverManager {
    void manageDrivers();
}

class Driver implements RideHandler, EarningsViewer {
    public void acceptRide() { System.out.println("Ride accepted"); }
    public void viewEarnings() { System.out.println("Earnings displayed"); }
}

class Admin implements DriverManager {
    public void manageDrivers() { System.out.println("Managing drivers"); }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, drivers only do what they’re supposed to, and admins handle their tasks separately. Everyone’s happy!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Dependency Inversion Principle&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Rule:&lt;/strong&gt; High-level module should not depend on low level modules. Both should depend on abstraction.&lt;br&gt;
&lt;strong&gt;Problem:&lt;/strong&gt;  Hard-Coded Notifications&lt;br&gt;
Your app sends SMS notifications, but now you want to add email and push notifications. Your code is tightly tied to SMS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SMSNotification {
    void send(String message) { System.out.println("SMS: " + message); }
}

class NotificationManager {
    private SMSNotification smsNotification;

    public NotificationManager() {
        this.smsNotification = new SMSNotification();
    }

    void notifyUser(String message) {
        smsNotification.send(message);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add email, you’d have to rewrite everything. What a pain!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Use an abstraction to decouple the notification manager from specific notification methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface NotificationService {
    void send(String message);
}

class SMSNotification implements NotificationService {
    public void send(String message) { System.out.println("SMS: " + message); }
}

class EmailNotification implements NotificationService {
    public void send(String message) { System.out.println("Email: " + message); }
}

class NotificationManager {
    private NotificationService notificationService;

    public NotificationManager(NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    void notifyUser(String message) {
        notificationService.send(message);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can easily switch between SMS, email, or any other notification method.&lt;/p&gt;

&lt;p&gt;Why You Should Care&lt;/p&gt;

&lt;p&gt;Following SOLID principles makes your code:&lt;/p&gt;

&lt;p&gt;Easy to understand (no messy “spaghetti” code).&lt;/p&gt;

&lt;p&gt;Easy to update (add features without fear).&lt;/p&gt;

&lt;p&gt;Fun to work with (seriously, your future self will thank you).&lt;/p&gt;

&lt;p&gt;So next time you build an app or write code, remember these five principles. They’ll make you the smartest coder in the room—and who doesn’t want that?&lt;/p&gt;

&lt;p&gt;What principle do you think is the coolest? Let me know!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
