5

Lets say you want a method to return both a generated object and a boolean indicating the success or failure of doing so.

In some languages, like C, you might have a function return additional objects by having reference parameters, but you cannot do this in Java since Java is "pass-by-value", so how do you return several objects in Java?

HaskellElephant
  • 9,819
  • 4
  • 38
  • 67
user496949
  • 83,087
  • 147
  • 309
  • 426
  • If `null` is never a valid return value and may be generated as a result of *normal code flow*, then why not use it to indicate the failure? (Java does not have standard -- or useful because it lacks Pattern Matching -- support for Maybe or Either constructs [but look at Functional Java](http://functionaljava.org/), although an additional class can always be created). –  Mar 04 '11 at 02:56
  • Also, C is also only pass-by-value. You can mutate an object [living in the JVM] *passed* to a method (by "value of reference"), just as one can modify an object [modifiable location in memory] *passed* to a method (by "value of pointer") in C. **I do not recommend this approach here**, but it does work: an object is itself. "pass-by-value" does not imply that an *object* is copied/cloned (arguably Java primitives are outside the scope of this statement). The most "primitive" type of object for which this works are arrays. Imagine: `string[] uglySideEffect = new string[1]; f(uglySideEffect);` –  Mar 04 '11 at 03:19
  • Does Java have out parameters? – smartcaveman Mar 04 '11 at 03:35
  • @smartcaveman No. But then can be emulated, fsvo (see previous comment). –  Mar 04 '11 at 03:42
  • Possible duplicate of [How to return multiple objects from a Java method?](http://stackoverflow.com/questions/457629/how-to-return-multiple-objects-from-a-java-method) – SymbolixAU Apr 13 '17 at 07:42

8 Answers8

3

You could do

class Result{

    Result(boolean result, Object value)
    {
        this.result = result;
        this.value = value;
    }

    public boolean getResult()
    { 
         return result; 
    }


    public Object getValue()
    { 
       result value; 
    }
    private boolean result;
    private Object value;

}

and have your function return an instance of Result

private Result myMethod()
{
   boolean result = doStuff();
   Object value = getValue();
   return new Result(result, value)
}
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • I can't up-vote because the use of a *mutable* Result object which is not needed in this case. –  Mar 04 '11 at 03:30
  • Better, I'll +1 since it addresses the comment [don't forget to add the final member modifier!] :-) It might also be nice to be mutually exclusive ... e.g. `return Result.Failure()` or `return Result.Success(value)` to prevent cases of returning "failure with value" (although the exact requirements need to be considered). –  Mar 04 '11 at 03:36
1

I would suggest one of two things, either return null and check for it wherever you need that object, or throw an exception in the event of an error.

On success just return the object.

Gunnar Hoffman
  • 1,226
  • 1
  • 11
  • 11
  • I would have to say it really depends on what your doing more than anything. Most of the time however, your right I would favor the exception. – Gunnar Hoffman Mar 04 '11 at 02:53
  • @iluxa "Not clean" depends entirely upon situation. In some cases it may be clean *in Java* (this is particularly because *Java is missing higher-level language features*) -- it just needs to be documented as defined behavior and able to capture the requirements. –  Mar 04 '11 at 03:25
  • @pst Completely correct, you expressed it much better than I. – Gunnar Hoffman Mar 04 '11 at 03:33
  • in my opinion, one should only return null when there's well... nothing meaningful to return. This should not be used to represent error conditions, tri-state conditions, etc., as these are hacky. Map.get() returning null is fully legit. ExistingFile.getContent() returning null is terrible – iluxa Mar 04 '11 at 19:26
1

Option 1: return one of these:

class ReturnValue {
  boolean isSuccessful;
  Object returnValue;
}

Option 2:

Object yourMethod() throws YourException {
}

Choose Option 1 is it's quite reasonable for the method to fail. Choose option 2 if the method should generally work, and the cases when it doesn't are indeed exceptional.

iluxa
  • 6,941
  • 18
  • 36
1

Pass a 1-element array to the method and get the result back in the array:

public boolean method(Object[] arg) {
    // ...
    arg[0] = result;
    return success;
}
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 1
    While this does "work", I can't up-vote simply because I'd stab someone for giving me code like this in *most* scenarios (I imagine someplace, somewhere, this *might* be okay for a specific situation). If there was a larger explanation of *why* this worked, I'd give an up-vote for the explanation itself. –  Mar 04 '11 at 03:29
  • @pst - It works because elements of an array can be modified in a called method. (IIRC, I picked up this idiom when browsing somewhere in Sun's Java api source itself.) BTW, I'll be sure to keep my distance if I see a knife in your hand. :-) – Ted Hopp Mar 04 '11 at 03:48
  • -) Put the reasoning up in the reply (+1) -- arrays are mutable objects. –  Mar 04 '11 at 22:38
1

Use a bean as the return type

public class Result
{
private boolean error = false;
private Object result = null; 
public Result(boolean error, Object result){ this.error=error; this.result=result;}

public boolean isError(){ return this.error; }
public Object getResult(){ return this.result; }
}

then your function becomes

public Result myFunc()
{
   //do stuff here
   Result r = new Result(false,retObj);

   return r;
}

Calling code does

Result result = myFunc();
if(result == null || result.isError())

{
//handle error
}
else
{
   Object actualResult = result.getResult();
   //process actualResult
}

You may use generics to pass any kind of class so that you may declare Result<TypeName> that returns TypeName rather than Object

mohaps
  • 1,010
  • 5
  • 10
  • I can't up-vote because this code allows too-many side-effects. The Result object should be *immutable* itself to reduce side-effects *and* simplify the code. Also the contract of the function should *never* return null if it it returns this Result which contains the "result status" (thereby completely replacing `null`). –  Mar 04 '11 at 03:26
  • It's a kludge to begin with. In an ideal world the sscenario described by the original poster wouldn't arise. There would be a return object or in case of error an exception would be raised, – mohaps Mar 04 '11 at 03:45
  • 1
    +1 then ;-) I do agree that the general approach is a kludge (in Java) -- I would likely just return `null`, but *shrug*. –  Mar 04 '11 at 04:06
1

How about creating a class for holding two objects:

public class Tuple<A,B>{
  A first;
  B second;
}

Then your method can be:

public Tuple<Boolean, Object> myMethod(){
    .
    .
    .
    Tuple<Boolean, Object> result = new Tuple<Boolean, Object>();
    result.first = success;
    result.second = generatedObject;
    return result;
}
HaskellElephant
  • 9,819
  • 4
  • 38
  • 67
  • May be interesting: http://functionaljava.org/ (which does a good bit of this boiler-plate). A +1 -- although in this case I believe an `Either` would be more appropriate (e.g. a disjoint Tuple) or an `Maybe` (something or nothing). See my other comments about mutability ;-) –  Mar 04 '11 at 03:38
0

http://www.osnews.com/story/20076/Multiple_Return_Values_in_Java

is that helpful?

you should make your own class...

Diainwater
  • 180
  • 1
  • 10
0

I would suggest to create a container object which will have a return code and an object. Alternatively, it could return null or an array of objects.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186