5

i have a method which will return an error code(int) and a result(int). If the error code is 0, the result is valid. In c++, this may like:

int method(int& result);

Java calls by reference, so if we change a object in a method, the change is visible by the caller. But, int is not a class, so I could't make is like this in java:

int method(int result);

And Integer and Long are immutable in Java, so change is not visible by the caller if i do it like this:

Integer method(Integer result);

Wrap the result into a Wrapper Class works! But, that's no so simple!

I work with c++ for long and move to java recently, this bother me a lot! could any one provide a solution?

=================================

well, in a conclusion, there are these flowing solutions:

  1. pass an array as parameter
  2. pass a wrapper as parameter
  3. return a pair
  4. return a wrapper containing error number and result
  5. throw exception
  6. pass a mutableint

1st and 2nd make my api ugly 3rd and 4th seems not so perfect about 5th, this method is frequantly called so i've to take efficiency into consideration 6th seems match my require most

thanks!

2
  • 4
    Just use exceptions. Updating variable passed into a method looks smelly. Commented Jan 11, 2012 at 13:34
  • You can throw exceptions in C++ also. ;) Commented Jan 11, 2012 at 13:54

11 Answers 11

4

Don't use return codes for errorcodes: use Exceptions; it is what they are for. Just return the actual result.

Sign up to request clarification or add additional context in comments.

Comments

3

You can't return more than one integer for your method. What you can do is:

  • Create a new object with 2 integer fields and let your method return an instance of that object (basically a wrapper);

  • Make your method return an array of 2 integers (or take it as a parameter);

  • Make your method return a String variable of the form <int 1>,<int 2>. You can then use the split() to get the numbers from the string and parse them back to integers.

  • Make your method throw the exception and return the number.

Comments

2

You are correct that you would need to wrap the values. If the call to method will not be too frequent, consider throwing an exception to report failure and exit cleanly otherwise. That would be the most Java-esque approach. I use this pattern in my C++ code as well (I do not like output parameters and return values in the same method unless there are other pressures requiring it).

However, performance sometimes requires the more C-system-call-ish style you are using. In that case I recommend you construct a Result type and an Error type that you can set the value of.

Something else to consider is to have a Generic (read "templated") class named TwoTuple<TYPE1, TYPE2> that you can use to pass pairs of values around. I've found that in Java I do a lot of pair-passing, though that might be a derivative of my personal style. :)

Comments

1

I would suggest creating a custom Object to hold both pieces of data, e.g.

public class ResultData {
    private int result;
    private int errorCode;

    public ResultData(int errorCode, int result) {
        this.result = result;
        this.errorCode = errorCode;
    }

    // Getters...
}

Then your method becomes:

public ResultData method() {
    // Do stuff
    return new ResultData(error, result);
}

Alternatively, as other answers have suggested, use Exceptions to signify if an error has occurred and that way if the method returns a result you can always be sure that it is valid. Catching the Exception signifies that an error occurred and you can handle it the way you would have handled the errorCode.

Comments

1

There are two ways to handle the scenario :- 1. Have a special values for error codes to distinguish them from result values ( if that is possible). For example, the indexOf() method in java's ArrayList returns -1 if the element is not present in the list, otherwise returns the positive index. 2. Use exceptions for erroneous conditions and always treat the return value as correct result. That is, if the method returns without any exception, assume exit code to be 0 and store the return value into result.

Creating a custom object to store the result and exit code might be an overkill.

Comments

0

There's a MutableInt component in the Apache Commons library. Since it's mutable, you can pass it by reference.

3 Comments

I'd be more inclined to use a javax.xml.ws.Holder<java.lang.Integer> for this.
Interesting, I'm not familiar with Holder. Is there a difference between using that instead of a one-element array?
No difference really, except that the intention is clearer with Holder. Which is a big difference after all.
0

Not very nice, but:

int method(int[] result) {
   result[0] = 1; // set result[0] as your out value
   // etc.
}

Using an array to create an "artificial reference" towards a single int.

1 Comment

Not so much as not very nice, but evil. Do it right, and they payback should become apparent within minutes.
0

Returning an error code is not a good practice in Java. Instead use exceptions... And list for multiuple values...

List<Integer> method(Parameter... paramteters)
{
   List<Integer> listOfValues = ...

   //some calculations

   if(errorCondition) throw new SomeException();

   //more calculations, if needed       

   return listOfValues;
}

Comments

0

Return an object containing the two integers, eg. using commons-lang v3 Pair

Pair<Integer, Integer> method(){
   return Pair.of(a,b)
}

2 Comments

Adding a 3rd party library to solve this problem is probably the worst suggestion until now ...
@jarnbjo - Hardly. It depends on OP's architecture, the number of times this situation is going to come up and other components of the library that may help in the project. Whilst exceptions may be preferable in this case, other users reading this thread who may want to return multiple values for non-error purposes would also find it useful.
0

Firstly, an int error code? Generally considered poor in Java. Exception is usual (but slow when executed). If it's actually common and/or performance is critical, then return something meaningful. Perhaps a nice new [2004] enum.

So in general, how to return multiple values. You could hack it and use AtomicInteger or similar. Please don't use an array!

Better would be to return a meaningful (probably immutable) object. Pair<,> is not a meaningful object. (There have been some suggestions for making this easier in a future version of the language.)

A more exotic way is to pass in a callback object. this is particularly useful if the result data differs depending upon possible result types. Have the method return void (or possibly the result of the callback) and add a parameter. Call a method depending upon the result type. Add as many arguments (within taste) and methods as useful. A typical caller would use an anonymous inner class, and not have to switch on error code. Of course, returning to the enclosing method again raises the problem of how to get the data out.

Comments

0

In your case, if you have a error, throw an appropriate exception. You have exceptions in C++ also.

Anything else is a valid result.


However to answer your question on how to return multiple values.

An approach I use in many places is to use a listener interface

 interface ErrorOrResult {
    void onError(int error);
    void onResult(int result);
 }

 a.method(errorOrResultImpl); // can use an anonymous implementation here.

As you can see, different types of result can be called any number of times with a variety of arguments.


You could return a Object with two fields. This is the most object orientated way.

If it bothers you that an object is created each time, you can pass an object as an argument. The simplest being an int[] which you reuse.

 int[] results = { 0, 0 };

 a.method(results);

An alterative is to return a long.

 long result = a.method();
 // split into two int values.

Or to make the method stateful.

 int error = a.method();
 int result = a.methodResult();

Or you can use the sign like Collections.binarySearch does

 int errorOrResult = a.method();
 if (errorOresult < 0)
    int error = ~errorOrResult;
 else
    int result = errorOrResult;

Given there are so many alternatives, it may a while before multiple return values are allowed.

1 Comment

@TomHawtin-tackline hehe, I agree the rest are ugly, but its not that it can't be done half a dozen ways.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.