Destructuring in Java and Kotlin

Biju Kunjummen
2 min readNov 24, 2023

Destructuring a data class in Kotlin is intuitive. Consider a data class “Address”:

data class Address(val street: String, val city: String, val state: String)
val address = Address(street = "1 Bowerman Dr", city = "Beaverton", state = "OR")

The “street” and “state” fields can be deconstructed from this variable the following way:

val (street, _, state) = address

See how the city can be ignored using “_” as the placeholder.

Now, Java 21, enables a similar deconstruction of fields of a Java Record along these lines, a wee bit less intuitive than the Kotlin version as it works with the instanceof operator(or with switch/case) and not outside of it:

record Address(String street, String city, String state) {
}
Address address = new Address("1 Bowerman Dr", "Beaverton", "OR");

if (address instanceof Address(var street, var city, var state)) {
assertThat(street).isEqualTo("1 Bowerman Dr");
assertThat(state).isEqualTo("OR");
}

// OR

switch (address) {
case Address(var street, var city, var state) -> {
assertThat(street).isEqualTo("1 Bowerman Dr");
assertThat(city).isEqualTo("Beaverton");
assertThat(state).isEqualTo("OR");
}
}

There are a few wrinkles here:

  1. Deconstructing requires the `instanceof` clause
  2. I may not be interested in deconstructing the city field but I am forced to provide a variable to hold the value of the field.

Point number 2 will be fixed with a new preview feature called “Unnamed patterns and variables”, using this the deconstructing looks similar to the Kotlin approach of using “_” for a placeholder for such fields:

if (address instanceof Address(var st, _, var state)) {
assertThat(st).isEqualTo("1 Bowerman Dr");
assertThat(state).isEqualTo("OR");
}

Nested Record Patterns

Consider a nested data class in Kotlin along these lines:

data class Address(val street: String, val city: String, val state: String)

data class Person(val name: String, val phone: String, val address: Address)

val person = Person(
name = "John Smith",
phone = "000-000-0000",
address = Address(street = "1 Bowerman Dr", city = "Beaverton", state = "OR")
)

Now say I want to get to the street and state for a person’s address, the way to do it in Kotlin would be something along these lines:

val (street, _, state) = person.address

Which works perfectly well, a similar approach works for Java 21 as well.

However, Java 21 expands on this with a way to get to the nested fields using a pattern and it looks something like this:

record Address(String street, String city, String state) {
}

record Person(String name, String phone, Address address) {
}

Person person = new Person("John Smith", "",
new Address("1 Bowerman Dr", "Beaverton", "OR"));

if (person instanceof Person(_, _, Address(var st, _, var state))) {
assertThat(st).isEqualTo("1 Bowerman Dr");
assertThat(state).isEqualTo("OR");
}

I have no big opinion on this, for my own code I would likely prefer to get to the nested instances using containing class fields.

--

--

Biju Kunjummen

Sharing knowledge about Java, Cloud and general software engineering practices