Multiple Return Values in Java
posted by Bjorn Raupach
Ok, lets assume you don't want to wait and have a solution right know. Since a method can only return a single object this has to be our wrapper for accessing the different return values. Some people might now claim: "Hey, but then I have to create another object. This is a waste in terms of performance." I won't go into further detail about that. Java is object-oriented! If you are afraid of creating single objects then you shouldn't use Java at all. Events are fired through Objects and many things more. So really there is nothing wrong with creating objects on a very frequent basis. javax.vecmath.Tuple3b is a good example for a simple Wrapper. It contains just three bytes and all it takes is just a single line: return new Tuple3b(aByte, bByte, cByte);
A better objection to dislike wrapper objects is the increase in lines of code that need to be written. The more you code the harder it is to read for others and for yourself in the future. This is a good point. Lets investigate what we can do about this. Take the following class for example. It acts as a wrapper for two objects:
public class TwoReturnValues { private Object first; private Object second; public TwoReturnValues(Object first, Object second) { this.first = first; this.second = second; } public Object getFirst() { return first; } public Object getSecond() { return second; } }A perfect object-oriented approach for having a wrapper around two objects. And since Java 1.5 supports autoboxing we don't have to give primitive types a special treatment, right? Well, this will really result in writing ugly code. Lets say some arbitrary methods needs to return a String s and an int n. No problem just write: return new TwoReturnValues(s,n);
For the callee it gets more cumbersome. Both getFirst and getSecond return java.lang.Object. Though the callee knows about the real types, he has to cast first to String and second to int. This is ugly and it is common knowledge that casts spread around your code should be avoided. Lets make things easier and add generics:
public class TwoReturnValuesChanging the signature of the method to TwoReturnValues >String,Integer< we not only got rid of those casts, but the code looks much more straightforward. One could argue that Generics itself are bloated fixings, but like I said if it is already in the language go ahead and use it. Wether or not the two accessore methods are needed in this specific case is open to dispute. Since this Object has no other purpose as to deliver values we can ignore encapsulation at least a bid and make first and second public. However then you should declare both fields final as well and regard the whole Object as immutable! This gives you also the advantage of having a thread-safe object (unless the fields itself are mutable).{ private R first; private S second; public TwoReturnValues(R first, S second) { this.first = first; this.second = second; } public R getFirst() { return first; } public S getSecond() { return second; } }
public final class TwoReturnValuesThe shown approach can easily be broadened to support more than two return values. As long as the callee knows how many objects he has to return and the number won't exceed lets say 2-4 you will be fine with this solution. And a line like (i,j,r,s,t,u,v,w) = foo() will doubtless convince not anybody to vote for supporting multiple return values in Java.{ public final R first; public final S second; public TwoReturnValues(R first, S second) { this.first = first; this.second = second; } public R getFirst() { return first; } public S getSecond() { return second; } }
Finally consider the case mentioned in the last paragraph. Lets say a method returns an unknown, but big number of values. Unfortunately here you really need to write many more lines of code to retrieve and convert all the data. Those who have worked with ResultSet and JDBC before know what I am talking about. An intermediate procedure would be returning an array of Objects, albeit you will end up using casts again if all the elements in the array have different types. But I believe even returning some kind of collection is better than adding support for multiple return statements.
0 comments:
Post a Comment