PERA LogoPERA Software Solutions GmbH
Returning multiple values from a method in Java

Returning multiple values from a method in Java

Problem

Sometimes it is necessary to return multiple values from a method. When you search the Internet for possible solutions, then you find a couple of suggestions:
  1. Return an
    Object[]
    or
    List<Object>
    .
  2. Modify an
    Object[]
    or
    List<Object>
    parameter.
  3. Return a
    Tuple<>
    with the values.
  4. Return a proper Object with the values as attributes.
  5. etc.
1. and 2. are very type unsafe because you have to know which type is at what position.
3. is at least typesafe but, if for example, you want to return multiple strings, then you have to know which tuple attribute contains what value.
4. is probably the cleanest solution but it means that you might end up with a lot of small "Result" classes.

Approach

Other curly brace languages like C++ or C# have built-in call-by-reference mechanism for this situation. C++ has reference parameter (
&
,
&&
) or pointer parameter (
&
,
*
). C# has the
out
and
ref
parameter modifiers.

Java on the other hand, has only call-by-value and so it is not possible to modify a given parameter directly. But if you call a method with an modifiable object, then you can modify the given object and store additional information. if we generalize this approach then we need a class which allows us to: Note that we don't need an initializing constructor because
out
parameters are only assigned in the called method and are not used to deliver a value to the called method.

So let's try with a very simple generic
Out<T>
: package com.pera_software.blog.returning_multiple_values; public class Out< T > { private T _value = null; public Out() { } public void set( T value ) { _value = value; } public T get() { return _value; } }

Examples

The following examples show how
Out<T>
can be used.

A simple example is splitting a string at a specified separator: package com.pera_software.blog.returning_multiple_values; import static org.junit.Assert.*; public class Example1 { public static void main( String[] arguments ) { String keyValue = "language=java"; Out< String > key = new Out<>(); Out< String > value = new Out<>(); assertTrue( splitString( keyValue, '=', key, value )); assertEquals( "language", key.get() ); assertEquals( "java", value.get() ); } public static boolean splitString( String s, char separator, Out< String > before, Out< String > after ) { int index = s.indexOf( separator ); if ( index >= 0 ) { before.set( s.substring( 0, index )); after.set( s.substring( index + 1 )); } return index >= 0; } } Another example simulates a technique which is used quite often in C++. You call a function which returns an error indicator and in case of an error fills an
error_code
. In the Java case we fill an exception output parameter: package com.pera_software.blog.returning_multiple_values; import java.io.*; public class Example2 { public static void main( String[] arguments ) throws IOException { Out< IOException > streamException = new Out<>(); try ( InputStream stream = openStream( "somefile.txt", streamException )) { if ( stream == null ) System.out.printf( "Couldn't open stream because %s%n", streamException.get().getMessage() ); } } public static InputStream openStream( String fileName, Out< IOException > streamException ) { try { return new FileInputStream( fileName ); } catch ( IOException exception ) { streamException.set( exception ); return null; } } } As a last example I'll show how the C#
TryParse
function could be implemented in Java: package com.pera_software.blog.returning_multiple_values; import static org.junit.Assert.*; public class Example3 { public static void main( String[] arguments ) { String number = "12345"; Out< Integer > integer = new Out<>(); assertTrue( tryParse( number, integer )); assertEquals( 12345, integer.get().intValue() ); } public static boolean tryParse( String number, Out< Integer > integer ) { try { integer.set( Integer.parseInt( number )); return true; } catch ( NumberFormatException exception ) { return false; } } }

Implementation

This is the
Out<T>
version which you can find in my JavaAidKit Library. This version however is more strict and doesn't allow
null
values: // Copyright 2016 Peter Most, PERA Software Solutions GmbH // // This file is part of the JavaAidKit library. // // JavaAidKit is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // JavaAidKit is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with JavaAidKit. If not, see <http://www.gnu.org/licenses/>. package com.pera_software.aidkit.lang; import java.util.*; /** * A class which can be used to return a value from a method via a parameter. The difference to * {@link com.pera_software.aidkit.lang.Ref} is that it doesn't need to be initialized with a value. * * {@code} * <blockquote><pre> * public static boolean splitString( String s, char separator, Out< String > before, Out< String > after ) { * int index = s.indexOf( separator ); * if ( index >= 0 ) { * before.set( s.substring( 0, index )); * after.set( s.substring( index + 1 )); * } * return index >= 0; * } * </pre></blockquote> * * @author P. Most */ public class Out< T > { private T _value = null; /** * No initializing constructor because {@code out} parameters are only supposed to be set in the * called method. */ public Out() { } /** * Sets the value if not null, otherwise throws a {@code NullPointerException}. * @param value the non-null value to set * @throws NullPointerException if value is null */ public void set( T value ) { if ( value != null ) _value = value; else throw new NullPointerException(); } /** * If a value is present, returns the value, otherwise throws {@code NoSuchElementException}. * @throws NoSuchElementException if there is no value present * @return the non-null value held */ public T get() { if ( _value != null ) return _value; else throw new NoSuchElementException(); } @Override public String toString() { String className = ( _value != null ) ? _value.getClass().getSimpleName() : Strings.EMPTY; return String.format( "Out<%s>: '%s'", className, _value != null ? _value : "null" ); } }

Related

The JavaAidKit Library. also contains a
Ref<T>
type, which extends
Out<T>
and contains an additional constructor which allows to set an initial value. Because
Ref<T>
extends
Out<T>
you can use it whenever an
Out<T>
is expected.

Tips

Notes

After writing
Out<T>
and
Ref<T>
I've found this article Simulating C# ref parameter in Java.

Comments

Comments aren't available on this site, but there is a reddit thread.