views:

262

answers:

4

I need to return/update a boolean while returning a list of stuff from a method. Java can't return tuples and I didn’t want to make a separate class for this, so figured I would pass the bool as an out param. That’s what our C++ client does, passes bool by reference. That would work for a normal class since java sort of has pass-by-ref for objects (see http://stackoverflow.com/questions/40480/is-java-pass-by-reference for a good discussion of this). But the “Wrapper” classes like Boolean store their primitive value as immutable, so it can't be updated in this way.

Using a boolean array (with one entry) seems hokey but is perhaps the simplest thing that works. Alternatively, could return the boolean and pass the created list back as an out param rather than as the return [but then the java client deviates from the C++, and it's best if they keep mostly the same approach- FYI need this in C# too.]

+8  A: 

No, Java doesn't have pass-by-ref for objects; it has "pass reference by value" which isn't the same thing.

You definitely can't pass anything as an "out" parameter or by reference in Java - although you could in C#.

Could you encapsulate the "Boolean plus list" into another type? Are they actually related? Using a boolean array is definitely pretty ugly. You could write a MutableBoolean wrapper type - but again, that's pretty ugly. Normally I'd say that returning two things suggests the method should be split up, but when one of them is a Boolean it can be fairly reasonable - like int.TryParse etc from C#.

Jon Skeet
@Jon - Java passes objects by ref and primitives by value. That's on the SCJP, i'm not sure what you mean by "Pass reference by value". If you pass an object as a parameter, modify the object and exit out, the object is changed. No "Copy" of the actual object exists.
Mech Software
Thanks. Yeah, I know java's terminology is messy, that's why I said "java sort of has pass-by-ref for objects (see question 40480 "Is Java pass by reference?" for a good discussion of this)."
Cincinnati Joe
@Mech Software - No - that's not on the SCJP exam - because it's wrong. http://bobcat.webappcabaret.net/javachina/faq/07.htm#pas_Q5
Nate
@Mech: When did I say that the *object* is copied? The *reference* is copied. The *reference* is passed by value. You never actually pass an object - you pass a reference. And @Cincinnati Joe - it doesn't need to be messy at all. "Pass a reference by value" isn't messy or inaccurate.
Jon Skeet
Calling them "references" was a bad move IMHO. They could have called them "pointers", "object IDs", "handles" or one of a million other things that didn't mean something completely different in C++.
finnw
@finnw: "pointer" would suggest it meant a physical address in memory, which it certainly doesn't have to. "Handle" would be somewhat better, although it has a slightly different meaning in Windows. "Object ID" might not be too bad. Really "reference" isn't too bad once you've got it, and it's pretty simple to get it.
Jon Skeet
+4  A: 

As you say, The Boolen wrapper class is immutable, so you cannot use it to receive your output variable.

Passing in a new list to receive the list result and returning the boolean would sound most natural to me, but you have a good reason; keeping the interface roughly the same over multiple implementations.

You could solve this problem by creating your own mutable Boolean and passing a reference to it, something like:

public class Example {
    public class BooleanResult {
        private boolean result;

        public void setResult(boolean value) { result = value; }
        public boolean getResult() { return result; }
    }

    // ....
    public List doSomething(BooleanResult out) {
        List list;
        boolean result;

        // ...

        out.setResult(result);

        return list;
    }
}

and use it like:

Example.BooleanResult out = new Example.BooleanResult();

List list = example.doSomething(out);

boolean result = out.getResult();
rsp
Yes, thanks for fleshing this out (Jon had also mentioned it in his answer). I think this is what we're going with since it mostly closely matches our C++ version.
Cincinnati Joe
+1  A: 

What I've done to return multiple values is to change the return type to return an object array. The [0] could be the bool and [1] could be the list.

The downside is that the caller must know to cast the returned objects appropriately from the object array, and the compiler can't check for you.

Edit: Here is a SO answer for returning a pair of values from Java.

aaaa bbbb
I like the pair idea - a coworker noted that Google Collections has a Pair, but it appears it's not in their 1.0 release.
Cincinnati Joe
According to this Google Collections does *not* have a Pair class yet: http://code.google.com/p/guava-libraries/issues/detail?id=203
finnw
+2  A: 

I need to return/update a boolean while returning a list of stuff from a method. Java can't return tuples and I didn’t want to make a separate class for this

I've encountered the same problem, and the best solution IMHO is usually:

Just forget your worries, and make a separate class.

I used to be hesitant about this, but classes are meant for encapsulating values, so go ahead and do it.

Chances are, once your function returns an instance of a custom class, you will find that there is additional functionality that fits well into that class, or other methods that could use the class as a parameter or return value, and soon the class will be fairly useful :-).

If you really don't want to do this, you can always stuff everything into a java.util.List or a java.util.Map and return that. But that's really ugly :-( I've done that as well, and come to regret it. It may seem simple at first, but as the code evolves and grows, readability suffers (was that a List of Integer, then Double, or vice versa?). Classes are much more helpful.

Note: If you feel a top-level regular class is overkill, you can use a nested class, which is nice for classes for "local use" only.

sleske
I happened to look at my notes from the recent CodeMash developer conference and recalled that this situation came up in a short presentation by Dick Wall of the Java Posse. He was speaking about Scala and said that it supports tuples for return types (he mentioned the controversial desire to add them to Java: http://stackoverflow.com/questions/457775/does-java-need-tuples). He said that in Java if you define a new "struct" class to return multiple things that you'd have to fully implement it with equals and hashcode methods and should test it - overhead for such a simple thing.
Cincinnati Joe
@Cincinnati Joe: Interesting point, thank you. As to "fully implement with equals etc.": I'd somewhat disagree. It's perfectly acceptable not to implement(override) those. You just need to remember that you should not blindly use equals() / hashcode() on a class without checking that they properly implement it. But that's a different can of worms...
sleske