Leepoint Java Reference Notes on the Java language and its standard library.

Returning more than one value

Java has no tuples. Which is mostly fine, because the workaround is better than a tuple.

A Java method returns one value. When you want two, the options are not equal.

A record — the right answer

record MinMax(int min, int max) { }

MinMax range(int[] values) {
    ...
    return new MinMax(lo, hi);
}

The caller gets named accessors:

MinMax r = range(data);
System.out.println(r.min());

This is better than a tuple would be, because the parts have names. pair.getFirst() tells the reader nothing; r.min() tells them everything. The declaration is one line, and you get equals, hashCode and toString free.

Before records, the same thing as a small class with two final fields — more typing, identical idea.

An array — usually a mistake

int[] range(int[] values) {
    return new int[] { lo, hi };
}

Short to write, unpleasant to use. The caller has to know that [0] is the minimum, nothing enforces it, and swapping them is a silent bug. It also forces both values to share a type.

Acceptable in a private helper five lines from its only caller. Not in an API.

Modifying a parameter — no

Java is pass-by-value throughout. Reassigning a parameter inside a method changes nothing for the caller:

void bad(int x) { x = 99; }      // caller's variable is untouched

Object references are also passed by value: you can modify the object a reference points at, but reassigning the parameter does not affect the caller’s variable. So “out parameters” as C or C# have them do not exist. Passing a mutable holder to be filled in works, and is worse than returning a record.

Optional, for absence

If the second value is really “did this succeed”, the answer may be one value that might not be there:

Optional<Customer> findById(String id);

Use Optional as a return type, not as a field or a parameter.

Two methods

If callers usually want one or the other, two methods are often clearer than one returning both. min(values) and max(values) read better than range(values).min() — unless computing them together is meaningfully cheaper, which for a single pass it can be.

Three or more

If a method wants to return four unrelated values, that is usually a sign it does more than one thing. Splitting it is a better fix than a wider record.