36

In javascript there is object destructuring so we can break down objects and just use the end key if the intermidiate objects are resused multiple times. e.g)

const person = {
  firstName: "Bob",
  lastName: "Marley",
  city: "Space"
}

So instead of calling person.<> to get each value we can destructure it like this

console.log(person.firstName) 
console.log(person.lastName) 
console.log(person.city) 

Destructured:

const { firstName, lastName, city } = person;

And call like this:

console.log(firstName)
console.log(lastName)
console.log(city)

Is there something similar in Java? I have this Java Object that I need to get the value from and have to call long intermediate object names like this:

myOuterObject.getIntermediateObject().getThisSuperImportantGetter()
myOuterObject.getIntermediateObject().getThisSecondImportantGetter()
...

I would like this destructure it somehow and just call the last method getThisSuperImportantGetter(), getThisSecondImportantGetter() for cleaner code.

lion_bash
  • 1,309
  • 3
  • 15
  • 27
  • That *is* how you "destructure" objects in Java. There are various ways you could convert from a string to properties, but there's little point, or you can introduce a jvm scripting language. Either way you'll pay a performance penalty. Or you can get the intermediate object and base your mainline code off that. "Clean" isn't generally associated with Java code when you're reaching into nested objects (and arguably it can be a little sketchy to do so depending on how easily you need to be able to modify/extend your code, e.g., Demeter). – Dave Newton Jun 13 '19 at 17:56
  • Java isn't known for being terse or expressive. You may want to look at another JVM language if those qualities are important to you. – Carcigenicate Jun 13 '19 at 17:57
  • No, it doesn't, but you can call a method with the result of the first getter, then inside that method work with the inner object. – Juan Carrey Jun 13 '19 at 17:57
  • 1
    you can assign the inner object to a 1 letter variable first and then call `a.getThisSuperImportantGetter()`; `a.getThisSecondImportantGetter();` – isaace Jun 13 '19 at 18:00

2 Answers2

28

Java Language Architect Brian Goetz has recently talked about adding destructuring to an upcoming version of Java. Look for the Sidebar: pattern matching chapter in his paper:

Towards Better Serialization

I strongly dislike the current proposal of the syntax, but according to Brian your use case will look like the following (please note, that at this point this is a proposal only and will not work with any current version of Java):

public class Person {
    private final String firstName, lastName, city;

    // Constructor
    public Person(String firstName, String lastName, String city) { 
        this.firstName = firstName;
        this.lastName = lastName;
        this.city = city;
    }

    // Deconstruction pattern
    public pattern Person(String firstName, String lastName, String city) { 
        firstName = this.firstName;
        lastName = this.lastName;
        city = this.city;
    }
}

You should than be able to use that deconstruction pattern for instance in an instanceof check like so:

if (o instanceof Person(var firstName, lastName, city)) {
   System.out.println(firstName);
   System.out.println(lastName);
   System.out.println(city);
}

Sorry, Brian does not mention any direct destructuring assignment in his examples, and I'm not sure if and how these will be supported.

On a side note: I do see the intended similarity to the constructor, but I personally do not like the current proposal that much, because the arguments of the "deconstructor" feel like out-parameters (Brian says as much in his paper). For me this is rather counter-intuitiv in a world where everybody is talking about immutability and making your method parameters final.

I would rather like to see Java jump over the fence and support multi-value return types instead. Something along the lines of:

    public (String firstName, String lastName, String city) deconstruct() { 
        return (this.firstName, this.lastName, this.city);
    }
Stefan Haberl
  • 9,812
  • 7
  • 72
  • 81
  • 2
    Multiple return types comes automatically once you have tuple types and destructuring built in into the language. – Aiono Mar 03 '21 at 11:26
  • 1
    It's worth noting that you'll get `deconstruct` for free when using `public record Person(String firstName, String lastName, String city){}`. I agree that out parameters are a bit odd. – Holger Mar 27 '21 at 11:49
  • Just curious: Can you give an example how a `record` might assist with destructuring? – Stefan Haberl Mar 29 '21 at 07:14
  • 2
    While the final syntax of the deconstruct declaration is not fixed, it is already given that records will get a default implementation, similar to how they get a default constructor today. So, with the record declaration, the deconstruction into variables matching their components will work out-of-the-box. – Holger Mar 31 '21 at 13:25
  • [Record Patterns](https://openjdk.org/jeps/440) are now part of Java 21. Just as @StefanHaberl I frowned on the syntax first. However it ensures that deep destructuring is possible in a type-safe way, especially in light of type erasure. – richardb Jul 19 '23 at 10:36
  • 1
    Funny, though, that in 2023 we‘re still talking about type erasure ;) – Stefan Haberl Jul 20 '23 at 05:44
23

As far as i know, java doesn't support this.

Other JVM language called Kotlin does support this

Kotlin | Destructuring Declarations