/ LOMBOK, KOTLIN

Comparing Lombok and Kotlin

I know about Lombok since a long time, and I even wrote on how to create a new (at the time) @Delegate annotation. Despite this and even though I think it’s a great library, I’ve never used it in my projects. The reason for this mostly because I consider setting up the Lombok agent across various IDEs and build tools too complex for my own taste in standard development teams.

Comes Kotlin which has support for IDEs and build tools right out-of-the-box plus seamless Java interoperability. So, I was wondering whether Lombok would still be relevant. In this article, I’ll check if Kotlin offers the same feature as Lombok and how. My goal is not to downplay Lombok’s features in a any way, but to perform some fact-checking to let you decide what’s the right tool for you.

The following assumes readers are familiar with Lombok’s features.

Lombok Snippet Kotlin equivalent

val

val e = new ArrayList<String>();
val e = ArrayList<String>()

@NonNull

public void f(@NonNull String b) {
    ....
}
fun f(b: String) {
  ...
}

Kotlin types can be either nullable i.e. String? or not i.e. String. Such types do no inherit from one another.

 @Cleanup

@Cleanup
InputStream in =
    new FileInputStream("foo.txt")
FileInputStream("foo.txt").use {
  // Do stuff here using 'it'
  // to reference the stream
}
  • use() is part of Kotlin stdlib
  • Referencing the stream is not even necessary

@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor

No equivalent as class and constructor declaration are merged

@Getter

public class Foo {
    @Getter
    private String bar;
}
class Foo() {
  var bar:String? = null
    private set
}
  • Generates a private setter instead of no setter
  • Not idiomatic Kotlin (see below)
public class Foo {
    @Getter
    private String bar;
    public Foo(String bar) {
        this.bar = bar;
    }
}
class Foo(val bar:String)

Takes advantage of merging class and constructor declaration with slightly different semantics

@Setter

public class Foo {
    @Setter
    private String bar;
}

 No equivalent but pretty unusual to just have a setter (does not favor immutability)

public class Foo {
    @Setter
    private String bar;
    public Foo(String bar) {
        this.bar = bar;
    }
}
class Foo(var bar: String)

@ToString

 No direct equivalent but included in data classes, see below

@EqualsAndHashCode

@Data

@Data
public class DataExample {
    private String name;
    private int age;
}
data class DataExample(
  var name: String,
  var age: Int)

 @Value

@Value
public class ValueExample {
  String name;
  int age;
}
data class ValueExample(
  val name: String,
  val age: Int)

Notice the difference between val and var with the above snippet

lazy=true

public class GetterLazyExample {
  @Getter(lazy=true)
  private Double cached = expensive();
}
class GetterLazyExample {
  val cached by lazy {
    expensive()
  }
}

@Log

@Log
public class LogExample {
  public static void main(String...
args) {
    log.error("Something's wrong here");
  }
}

No direct equivalent, but possible in many different ways

@SneakyThrows

@SneakyThrows
public void run() {
 throw new Throwable();
}
fun run() {
  throw Throwable()
}

There’s no such thing as checked exceptions in Kotlin. Using Java checked exceptions requires no specific handling.

@Builder

@Builder
public class BuilderExample {
  private String name;
  private int age;
}

BuilderExample b = new BuilderExampleBuilder()
  .name("Foo")
  .age(42)
  .build();
class BuilderExample(
  val name: String,
  val age: Int)

val b = BuilderExample(
  name = "Foo",
  age = 42
)

No direct equivalent, use named arguments instead.

 @Synchronized

public class SynchronizedExample {
  private final Object readLock = new Object();
  @Synchronized("readLock")
  public void foo() {
    System.out.println("bar");
  }
}

It’s possible to omit to reference an object in the annotation: Lombok will create one under the hood (and use it).

class SynchronizedExample {
  private val readLock = Object()
  fun foo() {
    synchronized(readLock) {
      println("bar")
    }
  }
}

synchronized() is part of Kotlin stdlib

 Experimental features

Lombok

Snippet

Kotlin equivalent

 @ExtensionMethod

class Extensions {
  public static String extends(String in) {
    // do something with in and
    return it;
  }
}

@ExtensionMethod(
  {String.class, Extensions.class}
)
public class Foor {
  public String bar() {
    return "bar".toTitleCase();
  }
}
fun String.extends: String {
  // do something with this and
  return it;
}

class Foo {
  fun bar = "bar".toTitleCase()
}

@Wither

 No direct equivalent, available through data classes

 @FieldDefaults

class Foo(val bar: String = "bar")

@Delegate

 Available in many different flavors

 @UtilityClass

@UtilityClass
public class UtilityClassExample {
  private final int CONSTANT = 5;
  public void addSomething(int in) {
    return in + CONSTANT;
  }
}
val CONSTANT = 5
fun addSomething(i: Int) = i + CONSTANT

@Helper

public class HelperExample {
  int someMethod(int arg1) {
    int localVar = 5;
    @Helper class Helpers {
      int helperMethod(int arg) {
        return arg + localVar;
      }
    }
    return helperMethod(10);
  }
}
class HelperExample {
  fun someMethod(arg1: Int): Int {
    val localVar = 5
    fun helperMethod(arg: Int): Int {
      return arg + localVar
    }
    return helperMethod(10)
  }
}

In conclusion:

  • Lombok offers some more features
  • Lombok offers some more configuration options, but most don’t make sense taken separately (e.g. data classes)
  • Lombok and Kotlin have slightly different semantics when a feature is common so double-check if you’re a Lombok user willing to migrate

Of course, this post completely left out Kotlin’s original features. This is a subject left out for future articles.

Nicolas Fränkel

Nicolas Fränkel

Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Also double as a trainer and triples as a book author.

Read More
Comparing Lombok and Kotlin
Share this