Immutable Object Using Lombok

Project Lombok is a java library that automatically plugs into your editor and builds tools, spicing up your java. Never write another getter or equals method again, with one annotation your class has a fully-featured builder, Automate your logging variables, and much more.

Project Lombok provides a @Data annotation which is a very useful annotation that includes @ToString, @EqualsAndHashCode, @Getter / @Setter and @RequiredArgsConstructor together. @Data generates all the boilerplate code that is required in simple POJOs (Plain Old Java Objects) and beans ie getters for all fields, setters for all non-final fields, toString, equals and hashCode , a constructor that initializes all final and non-final fields.

package org.wesome.dsalgo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Apple {
    String name;
    float price;
    Date date;
}
package org.wesome.dsalgo;

import org.junit.jupiter.api.Test;

import java.util.Date;

public class AppleTest {
    @Test
    public void setterMethodTest() {
        Apple apple = new Apple("Mcintosh", 1.1f, new Date());
        System.out.println(apple);
        /*  data members are publicly available, and can be modified   */
        apple.name = "Fuji";
        apple.price = 2.2f;
        apple.date = new Date();
        System.out.println(apple);
        /*  setters can modify data members   */
        apple.setName("Jonagold");
        apple.setPrice(3.3f);
        apple.setDate(new Date());
        System.out.println(apple);
    }

    /*  class can be extended to add or modify existing behaviour   */
    public static class AnotherApple extends Apple {
        @Override
        public void setPrice(float price) {
            super.setPrice(price + 100f);
        }
    }
}
plugins {
    id 'java'
    id "io.freefair.lombok" version "6.2.0"
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}

test {
    useJUnitPlatform()
}

 

Class created using project Lombok annotation @Data is not Immutable

@Value is the immutable version of @Data. @Value makes all fields private and final by default, and setters are not generated. The class itself is also made final by default, toString(), equals() and hashCode() methods are also generated, each field gets a getter method, and a all arguments constructor except for final fields that are initialized in the field declaration.

package org.wesome.dsalgo;

import lombok.Value;

import java.util.Date;

@Value
public class Apple {
    String name;
    float price;
    Date date;
}
package org.wesome.dsalgo;

import org.junit.jupiter.api.Test;

import java.util.Date;

public class AppleTest {
    @Test
    public void setterMethodTest() {
        Apple apple = new Apple("Mcintosh", 1.1f, new Date());
        System.out.println(apple);
        /*  data members are not publicly available, hence cannot be modified   */
        apple.name = "Fuji";
        apple.price = 2.2f;
        apple.date = new Date();
        System.out.println(apple);
        /*  setters are not generated   */
        apple.setName("Jonagold");
        apple.setPrice(3.3f);
        apple.setDate(new Date());
        System.out.println(apple);
    }

    /*  class cannot be extended to add or modify existing behaviour   */
    public static class AnotherApple extends Apple {
    }
}
plugins {
    id 'java'
    id "io.freefair.lombok" version "6.2.0"
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}

test {
    useJUnitPlatform()
}

 

Up to Release 6.4.1 Lombok Value annotation doesn't provide Defensive copies of mutable references 

@Value provides most of the required features to make a class immutable, such as making all fields private and final , not providing setters , make the class as final , each field gets a getter method, and a all arguments constructor except for final fields.

But till the time this article was written, the latest version of Lombok was 6.4.1 and @Vlaue doesn't provide the defensive copies of mutable references.

package org.wesome.dsalgo;

import lombok.Value;

import java.util.Date;

@Value
public class Apple {
    String name;
    float price;
    Date date;
}
package org.wesome.dsalgo;

import org.junit.jupiter.api.Test;

import java.util.Date;

class AppleTest {
    @Test
    public void setterMethodTest() {
        Apple apple = new Apple("Mcintosh", 1.1f, new Date());
        System.out.println(apple);
        apple.getDate().setYear(1);
        System.out.println(apple);
    }
}
plugins {
    id 'java'
    id "io.freefair.lombok" version "6.4.1"
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}

test {
    useJUnitPlatform()
}

follow us on