Should Java method arguments be used to return multiple values?

22,028

Solution 1

A long time ago I had a conversation with Ken Arnold (one time member of the Java team), this would have been at the first Java One conference probably, so 1996. He said that they were thinking of adding multiple return values so you could write something like:

x, y = foo();

The recommended way of doing it back then, and now, is to make a class that has multiple data members and return that instead.

Based on that, and other comments made by people who worked on Java, I would say the intent is/was that you return an instance of a class rather than modify the arguments that were passed in.

This is common practice (as is the desire by C programmers to modify the arguments... eventually they see the Java way of doing it usually. Just think of it as returning a struct. :-)

(Edit based on the following comment)

I am reading a file and generating two arrays, of type String and int from it, picking one element for both from each line. I want to return both of them to any function which calls it which a file to split this way.

I think, if I am understanding you correctly, tht I would probably do soemthing like this:

// could go with the Pair idea from another post, but I personally don't like that way
class Line
{
    // would use appropriate names
    private final int intVal;
    private final String stringVal;

    public Line(final int iVal, final String sVal)
    {
        intVal    = iVal;
        stringVal = sVal;
    }

    public int getIntVal()
    {
        return (intVal);
    }

    public String getStringVal()
    {
        return (stringVal);
    }

    // equals/hashCode/etc... as appropriate
}

and then have your method like this:

public void foo(final File file, final List<Line> lines)
{
    // add to the List.
}

and then call it like this:

{
    final List<Line> lines;

    lines = new ArrayList<Line>();
    foo(file, lines);
}

Solution 2

In my opinion, if we're talking about a public method, you should create a separate class representing a return value. When you have a separate class:

  • it serves as an abstraction (i.e. a Point class instead of array of two longs)
  • each field has a name
  • can be made immutable
  • makes evolution of API much easier (i.e. what about returning 3 instead of 2 values, changing type of some field etc.)

I would always opt for returning a new instance, instead of actually modifying a value passed in. It seems much clearer to me and favors immutability.

On the other hand, if it is an internal method, I guess any of the following might be used:

  • an array (new Object[] { "str", longValue })
  • a list (Arrays.asList(...) returns immutable list)
  • pair/tuple class, such as this
  • static inner class, with public fields

Still, I would prefer the last option, equipped with a suitable constructor. That is especially true if you find yourself returning the same tuple from more than one place.

Solution 3

See this RFE launched back in 1999:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4222792

I don't think the intention was to ever allow it in the Java language, if you need to return multiple values you need to encapsulate them in an object.

Using languages like Scala however you can return tuples, see:

http://www.artima.com/scalazine/articles/steps.html

You can also use Generics in Java to return a pair of objects, but that's about it AFAIK.

EDIT: Tuples

Just to add some more on this. I've previously implemented a Pair in projects because of the lack within the JDK. Link to my implementation is here:

http://pbin.oogly.co.uk/listings/viewlistingdetail/5003504425055b47d857490ff73ab9

Note, there isn't a hashcode or equals on this, which should probably be added.

I also came across this whilst doing some research into this questions which provides tuple functionality:

http://javatuple.com/

It allows you to create Pair including other types of tuples.

Solution 4

I do wish there was a Pair<E,F> class in JDK, mostly for this reason. There is Map<K,V>.Entry, but creating an instance was always a big pain.

Now I use com.google.common.collect.Maps.immutableEntry when I need a Pair

Solution 5

You cannot truly return multiple values, but you can pass objects into a method and have the method mutate those values. That is perfectly legal. Note that you cannot pass an object in and have the object itself become a different object. That is:

private void myFunc(Object a) {
    a = new Object();
}

will result in temporarily and locally changing the value of a, but this will not change the value of the caller, for example, from:

Object test = new Object();
myFunc(test);

After myFunc returns, you will have the old Object and not the new one.

Legal (and often discouraged) is something like this:

private void changeDate(final Date date) {
    date.setTime(1234567890L);
}

I picked Date for a reason. This is a class that people widely agree should never have been mutable. The the method above will change the internal value of any Date object that you pass to it. This kind of code is legal when it is very clear that the method will mutate or configure or modify what is being passed in.

NOTE: Generally, it's said that a method should do one these things:

  • Return void and mutate its incoming objects (like Collections.sort()), or
  • Return some computation and don't mutate incoming objects at all (like Collections.min()), or
  • Return a "view" of the incoming object but do not modify the incoming object (like Collections.checkedList() or Collections.singleton())
  • Mutate one incoming object and return it (Collections doesn't have an example, but StringBuilder.append() is a good example).

Methods that mutate incoming objects and return a separate return value are often doing too many things.

Share:
22,028

Related videos on Youtube

euphoria83
Author by

euphoria83

Love computers, technology and Apple. Wanna be entrepreneur.

Updated on July 09, 2022

Comments

  • euphoria83
    euphoria83 almost 2 years

    Since arguments sent to a method in Java point to the original data structures in the caller method, did its designers intend for them to used for returning multiple values, as is the norm in other languages like C ?

    Or is this a hazardous misuse of Java's general property that variables are pointers ?

  • euphoria83
    euphoria83 about 15 years
    That's precisely my question. As with Date, should we not mutate any object passed by reference ?
  • euphoria83
    euphoria83 about 15 years
    Lisp allows it beautifully too. Your solutions are correct and obvious, except for the use of Generics. Can you explain that in short as this use is new to me ?
  • euphoria83
    euphoria83 about 15 years
    I know exactly what you are saying, but constructing objects just for the purpose of returning multiple values has proved to be confusing in practice, certainly for me. It definitely goes against what a class is supposed to be.
  • euphoria83
    euphoria83 about 15 years
    Just that then there exist a couple of class which are not doing anything except sitting there for value transfer. I try to make a class only if it does/holds something significant.
  • Adeel Ansari
    Adeel Ansari about 15 years
    Collections.sort() is a valid use, if one is required to not affect the original, pass the copy. Otherwise, its quite clear that the method sort would play with the passed list.
  • euphoria83
    euphoria83 about 15 years
    actually Google is doing some great work in filling up the holes in Sun's Java implementation. These need not be mistakes. But they definitely were needed for better hacking.
  • Alan Moore
    Alan Moore about 15 years
    Objects are never passed by reference; object references are passed by value. But that's not what this thread is about.
  • TofuBeer
    TofuBeer about 15 years
    I am not 100% sure it will work for you, but I added to my post of what I might do in your shoes.
  • euphoria83
    euphoria83 about 15 years
    Great. Thanks. I already know such tricks in the book. But appreciate your effort.
  • Jonathan Holloway
    Jonathan Holloway about 15 years
    I added the Pair implementation link and a link to javatuple - which looks pretty good. Hope that helps.