4 tips to return multiple values

Java directly does not support returning multiple values from method. During time some workarounds were invented. I personally like Immutables approach.

Return array of values

Only one data type can be used, semantic of array items is not directly visible:

class Test { 
  void test() { 
    String[] name = getCompleteName(); 
    
    System.out.println(name[2]+", "+name[1]); 
  } 
  
  String[] getCompleteName() { 
    DbPerson person = ...; 
    return new String[]{person.getName(), person.getSurname()]; 
  } 
}

This brings many issues:

  • Necessity to check length
  • Test NULL values
  • Semantics of fields is lost
  • Only one data type can be used

Use higher structure like Pair, List, Map

Use for example Pair:

class Test { 
  void test() { 
    Pair<String, String> name = getCompleteName(); 
    
    System.out.println(name.getSecond()+", "+name.getFirst()); 
  } 
  
  Pair<String, String> getCompleteName() { 
    DbPerson person = ...; 
    return new Pair<>(person.getName(), person.getSurname()); 
  } 
}

I don’t like this approach for the same reason as array - you lose semantics of fields and only one data type can be used.

Define returned type as class

Define nested/inner class with necessary members:

class Test { 
  void test() { 
    CompleteName name = getCompleteName(); 
    
    System.out.println(name._surname+", "+name._name);
  } 
  
  public class CompleteName { 
    String _name; 
    String _surname; 
  } 
  
  CompleteName getCompleteName() { 
    DbPerson person = ...; 
    CompleteName res = new CompleteName(); 
    
    res._name = person.getName(); 
    res._surname = person.getSurname(); 
    
    return res; 
  } 
}

I don’t like accessing instance variables without accessors. But adding constructors/getters/setters is sooooo exhaustive. Fine for 2 fields but what about 10 or 20?

Use Immutables

Newest possibility and my favorite is to use library called Immutables. It allows you to define interface using with getters and generates builder/access methods according to it:

class Test { 
  void test() { 
    CompleteName name = getCompleteName(); 
    
    System.out.println(name.getSurname()+", "+name.getName()); 
  } 
  
  @Value.Immutable 
  public interface CompleteName { 
    String getName(); 
    String getSurname(); 
  } 
  
  CompleteName getCompleteName() { 
    DbPerson person = ...; 
    
    return ImmutableCompleteName 
      .builder() 
      .name(person.getName()) 
      .surname(person.getSurname()) 
      .build(); 
  } 
}

This approach has many positive properties:

  • Semantic is kept
  • You may use arbitrary data types
  • Basic validation is done automatically (NULL checks, …)
  • You can define more complex validation using annotations