-1

I can't get return in function's aaa parameters a and b like:

public static void aaa( boolean a , Integer b)
{
    a=true;
    b =2;
}
public static void main(String[] args)
{

    boolean a=false;
    int b=1;
    aaa(a,b);
    lg.info("{} {}",a,b );
}

I will get same false 1 in output.

Each time when I need to have more than one return in function I must create class-holder:

public static class BoolAndIntHolder
{
    boolean a ; 
    Integer b ;
}


public static void aa(BoolAndIntHolder s)
{
    s.a =true;
    s.b =2;
}

public static void main(String[] args)
{
    BoolAndIntHolder s= new BoolAndIntHolder();
    s.a = false;
    s.b=1;
    aa(s);
    lg.info("{} {}",s.a,s.b );
}

This gives true 2 in output as wanted.

But this looks so horrible each time to create different class holders. Is here any hacks how to write code in such situation in less dramatic way?

UPD

Looks like I must use data class'es in order to return several values since it is less complicated way. Solution bellow looks ugly for me. Is it possible to solve task in more elegant way?

enum TRUE_FALSE_ERR {TRUE,FALSE,ERR};

static TRUE_FALSE_ERR aaa()
{
    if (isConnected())
    {
        if getResult() return TRUE_FALSE_ERR.TRUE else 
            return TRUE_FALSE_ERR.FALSE;
    } else
    return TRUE_FALSE_ERR.ERR;
}


public static void main(String[] args)
{
    switch (aaa()) {
    case ERR:
        lg.info("ERR");
        break;
    case TRUE:
        lg.info("TRUE");
        break;
    case FALSE:
        lg.info("FALSE");
        break;
    default : lg.info("default"); 
    }
}
vico
  • 17,051
  • 45
  • 159
  • 315
  • @NicholasK I don't think this counts as a duplicate – Roy Shahaf Dec 28 '18 at 17:06
  • You can create a method that returns an Object array, where index 0 is your Boolean, and index 1 is your integer. So, when you call this method, remember to specify the array index used. `Object[] obj = aaa(a, b); lg.info("{} {}", obj[0], obj[1]);` – Fabian Brandão Dec 28 '18 at 17:12
  • @FabianBrandão they COULD do that, but it's a really bad idea... – Roy Shahaf Dec 28 '18 at 17:14
  • @FabianBrandão I mean, if you're going to have an ugly workaround, at least make it better (like passing in a map from variable name to value) – Roy Shahaf Dec 28 '18 at 17:15

4 Answers4

1

If two primitives are not inter-connected, you should (in theory) calculate them in separate methods. If they are inter-connected, it makes sense to encapsulate them in a data class (which can later be extended to have behavior that is related to these primitives)

Roy Shahaf
  • 494
  • 5
  • 10
  • 1
    Instead of using a "void" return type, use a bool return type for one method, and a int return type for the other method. – Baruch Atta Dec 28 '18 at 17:11
  • I have updated my question body with sample with data class that looks ugly for me. Is it possible to solve this task in more elegant way? – vico Dec 29 '18 at 10:29
1

Alternative 1: Lambda callback

You could make the method call the caller back with the results.

interface Callback {

    void accept(boolean b, int i);
}

public static void aaa(Callback callback) {
    callback.accept(true, 2);
}

public static void main(String... args) {
    aaa((a, b) -> System.out.println(a + " " + b));
}

Prints:

true 2

Alternative 2: AtomicBoolean and AtomicInteger

You could pass in AtomicBoolean and AtomicInteger objects. These can be set by the function and then read by the main method.

public static void bbb(AtomicBoolean b, AtomicInteger i) {
    b.set(true);
    i.set(2);
}

public static void main(String... args) {
    AtomicBoolean atomicBoolean = new AtomicBoolean(false);
    AtomicInteger atomicInteger = new AtomicInteger(0);
    bbb(atomicBoolean, atomicInteger);

    System.out.println(atomicBoolean.get() + " " + atomicInteger.get());
}

Prints:

true 2

This kind of thing is a bit of hack though.

Alternative 3: Find the right abstraction

If you want to return two things from a function, it would be better to pull out a well-named class to represent them. The right abstraction will make your code easier to understand in the future. Hint: BoolAndIntHolder is not a good abstraction. You need to ask yourself "what does it represent in the language of the domain?"

Alternative 4: Split into two functions

In my experience, in most of the cases where I've wanted to return two results, I've found it's better to write two separate functions. It may be less "efficient" but usually produces code that is easier to understand and easier to modify. It decouples the two concepts. I don't know what your situation is though, so it's hard to know whether this applies here.

ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
1

That's how Java is designed, you can't return more than one value. Most of the time a wrapper object is used like you tried, if you intend to reuse created object in many places then it's a good approach but if you want to use this object only in one place then an easy alternative since Java 9 is to use Map in one line:

public static Map<String, Object> aa(){
...
return new Map.of("a", true, "b", 2);

Ff returned arguments are of different type then you have to cast, but if you just want to print objects and they have toString method overridden then casting isn't necessary:

lg.info("{} {}", map.get("a"), map.get("b") );
Michael Dz
  • 3,655
  • 8
  • 40
  • 74
0

You can use Java Observable values, such as:

public static void main(String[] args) {
    SimpleBooleanProperty a = new SimpleBooleanProperty(false);
    SimpleIntegerProperty b = new SimpleIntegerProperty(1);
    changeValue(a, b);
    System.out.println(a.getValue() + " :: " + b.getValue());
}

public static void changeValue(SimpleBooleanProperty a, SimpleIntegerProperty b) {
    a.setValue(true);
    b.setValue(2);
}

With this methodology, you can use 'a' and 'b' to be notified when other object is modified, for example:

public static void main(String[] args) {
    SimpleBooleanProperty a = new SimpleBooleanProperty(false);
    SimpleBooleanProperty aNotifier = new SimpleBooleanProperty();
    a.bind(aNotifier);

    SimpleIntegerProperty b = new SimpleIntegerProperty(1);
    SimpleIntegerProperty bNotifier = new SimpleIntegerProperty();
    b.bind(bNotifier);

    changeValue(aNotifier, bNotifier);
    System.out.println(a.getValue() + " :: " + b.getValue());
}

public static void changeValue(SimpleBooleanProperty a, SimpleIntegerProperty b) {
    a.setValue(true);
    b.setValue(2);
}