11

Sometimes you want to return multiple values from a function. How is this normally done in Java?

One option is to use an array, like this Python snippet that returns a list or tuple:

value, success = read_unreliably()
if success:
    print value

Another option would be to return a hash/dict, like this JavaScript example:

var result = readUnreliably()
if (result.success) {
    alert(value);
}

One more would be to create a custom object just for this purpose, like this Java example:

ReadUnreliablyResult result = readUnreliably()
if (result.getSuccess()) {
    System.out.println(result.getValue());
}

Of course you can also just use some global variables to store what you need instead of passing things around, but let's just say that's not an option.

Mike M. Lin
  • 543
  • 1
  • 4
  • 13
  • Do "real" java people really go through the trouble of using public getters and setters to hide fields on little internal classes like that? Just curious. – Chris Farmer Jul 25 '11 at 23:50
  • 3
    Yes, most do. Since many frameworks expect the JavaBean standard, you can regret not having getters and setters. In any case, your IDE will generated them for you. – Eric Wilson Jul 26 '11 at 02:34
  • 3
    Or you can just leave them out, based on the YAGNI principle. But that doesn't seem to happen as often as one might expect. – Tyler Jul 26 '11 at 02:46
  • @FarmBoy: I guess I understand for beans and such, but the OP implies that this is just a one-off class designed to return multiple values. – Chris Farmer Jul 26 '11 at 17:03
  • @ChrisFarmer I guess that with that context, I've never seen a 'real' Java programmer create a class for this purpose. – Eric Wilson Jul 26 '11 at 18:22
  • Put references in the method parameters instead, where you add the result. void getResult(Indata id, Result a, Result2 b) and store result in a and b. – Per Alexandersson Aug 29 '11 at 12:16
  • In this case, return a java.util.Optional. – Reinstate Monica Apr 21 '16 at 18:53

6 Answers6

26

How is this normally done in Java?

Painfully.

One option is to use an array, like this Python snippet that returns a list or tuple...

Another option would be to return a hash/dict, like this JavaScript example...

These techniques don't work well in Java; the values would have to be downcast from Object.

One more would be to create a custom object just for this purpose, like this Java example...

This is most common, but it is tedious to create all those little classes. In C++ it is common to use std::pair but this is not commonly done in Java.

With Lombok it is quite easy to create little custom objects:

@RequiredArgsConstructor
public class X {
  private final boolean status;
  private final byte[] data;

}

kevin cline
  • 33,608
  • 3
  • 71
  • 142
  • 10
    "How is this normally done in Java?" "Painfully." lol as a Java developer I have to +1 you for that – TheLQ Jul 26 '11 at 06:16
  • Using a compact immutable struct-like class is not so painful... It is really like writing a C struct... – Guillaume Jul 26 '11 at 14:34
  • 1
    @Guillaume - sure, but all those little things add up in both time and space. I don't know why the Java community hasn't adopted a standard set of generics like "class Pair { public T1 first; public T2 second; ... }"; in modern languages you just "return a, b" ; and then write "x,y=f()"; – kevin cline Jul 26 '11 at 14:55
  • 1
    I'm sure some 'ancient' language are able to do it too :) IMHO I found multiple return values can lead to total mess, and if you need to add another return fields, you just have to update your struct like class without to change your method signature. – Guillaume Jul 26 '11 at 15:24
  • 1
    That "Painfully." struck me hard, yes its exactly what I feel as Java developer when I meet similar situations. – artjom Sep 25 '13 at 10:19
  • Altho you can use pair in C++, declaring the result (before C++11 "auto") and accessing the parts with "first" and "second" was so painful that I usually preferred creating a small struct anyway. I do the same in Java (small nested class, without getters and setters) except in some very simple cases where I have used an array. – marcus Sep 25 '13 at 17:35
  • @marcus: The getters and setters aren't the problem. You can do without those. It's the constructor. I don't want to write or read `x = new X(); x.setA(1); x.setB("b");` I want to write `return new X(1, "b");` – kevin cline Sep 25 '13 at 20:21
  • That's when I have to choose between writing the constructor myself or using an array, which can be constructed directly. I haven't tried Lombok yet. – marcus Sep 25 '13 at 21:54
  • There's yet another option: make your multiple-return-function the constructor itself. In this case you won't even need to write "return" :-) You'll put the burden on the caller to write "new", though. – marcus Oct 17 '13 at 14:43
13

Yes, the way to create a struct / tuple / record in Java is by creating a class. If it's only for internal use, I prefer to use a small immutable struct-like class with public fields.

Examples:

public class Unreliably {
    public final boolean success;
    public final int value;
    public Unreliably(boolean success, int value) {
        this.success = success; this.value = value;
    }
}

This is much easier to do in Scala:

case class Unreliably(success: Boolean, value: Int)
Jonas
  • 14,867
  • 9
  • 69
  • 102
  • 8
    Actually, in Scala, you'd probably generally just return a `Tuple2[Boolean, Int]`. Although in this *specific* example, you'd return an `Option[Int]`. – Jörg W Mittag Jul 26 '11 at 00:48
  • 2
    So this answers Chris Farmer's question (in the Q's comments) that real Java people don't necessarily create getters and setters for little internal classes. You are a "real" Java person, right? – Mike M. Lin Jul 26 '11 at 03:14
  • 2
    In other news, there are no true Scotsmen. – Joseph Weissman Jul 26 '11 at 04:10
5

For the example you have given, throwing an exception would be the most standard way to handle it:

try {
    result = readUnreliably();
    System.out.println(result);
} (catch IOException e) {
    System.out.println("Could not read file");
}

Moreover, if you strive to have functions that "Do One Thing" the feature of returning multiple values is less necessary, though occasionally convenient.

Eric Wilson
  • 12,071
  • 9
  • 50
  • 77
4

We have a Pair generic class which can store one instance of A and one instance of B. You can probably create a Triplet or Quadruplet in the same manner.

public class Pair<A, B>
{
    ...
}
Raku
  • 1,083
  • 6
  • 12
  • 1
    this makes for some REALLY unreadable code though. if a method returns `Pair`, what does that mean? what do these values represent? you can't possibly know without reading the implementation of the method. – sara Mar 22 '16 at 09:57
1

In Java, your function would return an object (or perhaps null in the case of a failure). This way, multiple pieces of data can be returned.

Scott C Wilson
  • 3,908
  • 20
  • 25
1

There is no explicit way to return multiple variables in Java, however there are a few approaches:

  1. The first is to go the way of the array. This only really works if you have everything as the same data type or can temporarily convert them to one type.
  2. The second way is to create a class for the purpose of transferring multiple variable types. At my work we refer to these as DTOs or Data Transfer Objects.