Pankaj Gadge
Pankaj Gadge

Reputation: 2814

Pass value to caller without using `return`

I have a following two functions where, I need to set a boolean value in second function but I need to use that value later in the calling function.

Restrictions:

  1. I cannot return the boolean value in the second function.
  2. I can't use it as a global variable due to thread safety.

What is the most efficient and cleanest way to achieve this?

private void F1()
{
    boolean foo = false;
    List<String> result = F2(foo);

    if(foo)
    {
        // do something
    }
}

private List<String> F2(boolean foo)
{
// Logic to set the result
    List<String> result = new ArrayList();

    if(condition)
    {
        foo = true;
    }

    return result;
}

Upvotes: 1

Views: 99

Answers (2)

njzk2
njzk2

Reputation: 39406

Assigning foo is entirely useless, because that would not be reflected in the calling method.

There are several ways of achieving the same result, though:

Use an array:

private void F1() {
    boolean foo[] = new boolean[1];
    List<String> result = F2(foo);

    if(foo[0]) {
        // do something
    }
}

private List<String> F2(boolean[] foo) {
// Logic to set the result
    List<String> result = new ArrayList();

    if(condition) {
        foo[0] = true;
    }

    return result;
}

Or any other structure that can hold a value without changing its reference (an AtomicBoolean is an example).

Change the way you handle the return value:

private void F1() {
    List<String> result = F2();

    if(result != null) {
        // do something
    }
}

private List<String> F2() {
// Logic to set the result
    List<String> result = new ArrayList();

    if(condition) {
        return result;
    }

    return null;
}

Returning null where an Object is expected is a common way to indicate that something went wrong and the result is not to be considered valid. Not to be mistaken with an empty result List, which could indicate that everything is fine, there is just nothing to be returned.

Throw an exception:

private void F1() {
    try {
        List<String> result = F2();
        // do something
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private List<String> F2() {
// Logic to set the result
    List<String> result = new ArrayList();

    if(!condition) {
        throw new Exception("Condition not met");
    }

    return result;
}

Here it can be a checked or unchecked exception, depending on the effect you want. Also commonly used, for example to indicate that the input is incorrect, that there has been some error due to external causes (I/O), that the system is in a state that does not allow this operation...

Upvotes: 1

John Kugelman
John Kugelman

Reputation: 361809

You could use a mutable wrapper around boolean to simulate pass-by-reference. AtomicBoolean can be reappropriated for this purpose. You wouldn't be using it for its atomic-ness, just the ability to set its value in one function and read it in another.

private void F1()
{
    AtomicBoolean foo = new AtomicBoolean(false);
    List<String> result = F2(foo);

    if(foo.get())
    {
        // do something
    }
}

private List<String> F2(AtomicBoolean foo)
{
// Logic to set the result
    List<String> result = new ArrayList();

    if(condition)
    {
        foo.set(true);
    }

    return result;
}

Another common, though even kludgier, way to do this is with a 1-element array.

boolean[] foo = new boolean[] {false};

The same trick applies. F2 would do

foo[0] = true;

This is pretty ugly, but you'll see it from time to time, because hey, sometimes you gotta do what you gotta do.

Upvotes: 3

Related Questions