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;
}
You've already created at least one inconsistency, and a particularly damning one at that - treating functions differently from other values. A function declaration is conceptually the same as binding a variable to an anonymous function, but you're asserting that "regular" variables don't get hoisted while function declarations do. So...
f()
function f() { /* ... */ }
Works, but...
f()
var f = function() { /* ... */ } // Pretend this is anonymous function syntax
Doesn't. (And if you don't allow passing functions around like any other value, your language is horribly crippled.) Next, what happens if a function is redefined?
f()
function f() { /* definition 1 */ }
...
function f() { /* definition 2 */ }
If you treat this as an error, you're once again rejecting functions as values. There's no reason you shouldn't be able to do:
var f = function() { /* def 1 */ }
f = function() { /* def 2 */ }
So let's assume you'll allow the function to be redefined. How do you deal with lexical scoping?
function f() { /* definition 1 */ }
function bar() {
f()
function f() { /* definition 2 */ }
If you hoist definition 2 to the top of bar
's scope, you end up with this:
function f() { /* definition 1 */ }
function bar() {
function f() { /* definition 2 */ }
f()
Which means you can never call the outer definition from a nested scope unless you give the inner function a different name. Moreover, in any other language, the meaning of the above program is independent of the choice of name for definition 2. The hoisting rule changes the meaning depending on whether there's a name collision or not. On the other hand if you don't hoist definition 2 to the top of bar
, you've broken your own rule.
Best Answer
It's not a sign of anything, and is not neither good nor bad design or coding style.
Returning multiple values can actually be appropriate and allow to write less code. Let's take an example of a method which takes a string like
"-123abc"
and converts it to an integer like-123
:returns both:
How can we refactor this?
1. Exceptions
We can add exceptions, if the language supports them. Remember than in most languages, exceptions are expensive in resources. It means that if you have to deal with lots of non-numbers, it's better to avoid to throw an exception every time the string cannot be converted to a number.
2. New class
We can create a class and return an instance of an object of this class.
For example:
Is it easier to understand? Shorter to write? Does it bring anything? I don't think so.
3. Out parameters
If the language supports it, we can also use
out
parameters. This is the approach of C# where returning multiple values is not possible. For example, when parsing a number, we use:bool isSuccess = int.TryParse("-123abc", out i)
. I'm not sure how is it better to useout
parameters compared to multiple values. The syntax is not obvious, and even StyleCop itself (the tool used to enforce the default Microsoft style rules on the code) complains about those parameters, suggesting to remove them when possible.Finally, in languages as C# where there is no such a thing as returning multiple values, things are progressively added to imitate the behavior. For example,
Tuple
was added to allow returning several values without having to write your own class or useout
parameters.