开发者

Return multiple values from a Java method: why no n-tuple objects?

开发者 https://www.devze.com 2023-04-06 08:45 出处:网络
Why isn\'t there a (standard, Java certified) solution, as part of the Java language itself, to return multiple values from a Java method, rather than developers having to use their own means, such as

Why isn't there a (standard, Java certified) solution, as part of the Java language itself, to return multiple values from a Java method, rather than developers having to use their own means, such as Maps, Lists, Pairs, etc.? Why does Java not support n-tuple objects?

Especially thinking for trivial private methods that may modify two objects together (in tandem), and in开发者_JAVA百科 which case a typed-object as a return sounds overkill.


I assume the OP means "Why does Java not support n-tuple objects?". Python, Haskell, Lisp, ML etc have heterogeneous n-tuple capabilities. Also often times the ability to apparently return multiple objects in a language is syntactical sugar (ie in python return 'a','b').

The reason of course is language design and consistency. Java prefers being very explicit and does not like anonymous data structures (although I wish we had anonymous closures).

For example in Java there is no way to say I would like a callback that takes these type parameters and returns this. Some people feel this a huge weakness others like the consistency and explicitness.

IMHO although its annoying I frequently combat this issue by making static inline classes:

private static class Combo {
   String name;
   int weight;
}

Yes its tedious but then later on I often reuse and refactor those classes making them top level and adding behavior. Infact one of the advantages with going this route is that its much easier to add new fields where is the anonymous data structure (like in FP languages) it becomes much more difficult to add a field (you end up changing a ton of code).

I should note that for 2-tuples some people use (or abuse) java.util.Map.Entry as there is an java.util.AbstractMap.SimpleEntry in Java 6. Also Some people now use Commons Lang3's Pair support (2-tuple).

Scala has n-tuple support by sort of cheating and having a whole bunch of 2-16 tuple interfaces that are standard in the language and are syntactically hidden from the programmer.

For purely educational reasons you may want to see how other languages accomplish this.

UPDATE: for Java 8

Java 8 will/maybe (so heres my number... call me maybe) support an interface called java.lang.BiValue with a concrete implementation that you can use called java.lang.BiVal . These classes are to help support the new lambda functionality. But notice this is only for 2-tuples.

UPDATE: for 2015

Java 8 did not gain support for tuples.

UPDATE: from author 2015

If you still would like tuple support there are three libraries that support tuples well:

  • javatuples - Supports JDK 5 and above. Up to 10-tuple.
  • JOOλ - From the author of jOOQ but requires JDK 8.
  • Commons Lang 3 - Now supports a Triple (3-tuple) and supports JDK 6 and above.


Java methods return exactly zero or one value; that is the standard for java. If you need multiple values returned, create an object with the multiple values and return it.


If you want to return two objects you usually want to return a single object that encapsulates the two objects instead.


There are plenty of hackish ways to accomplish this, one way would be to return an Object[], but then you've got indices to worry about, and null pointer checks, it just gets nasty. Another way is to return a String, but then you've got to parse it, and it gets nasty.

I think the real question is why?

Here's the rub - If I were working on a project with you, and I saw this type of behavior, I'd rewrite it so you could see how it should be handled. If you provide a code sample, I'll rewrite it to illustrate.

Write your methods with a single responsibility, if they need to return more data than they have the ability to, you should likely either use an object, or break it into smaller methods.


Because returning multiple value from a method is not a recommended practice ( in Java ).

If you need unrelated values from a method you need a different datastructure like an object containing those values. If you need multiple instances of the same class ( ie several Strings ) you need to return either an array, or some collection depending on your needs.

Returning multiple values in other languages ( Go for instance ) are used for instance to return an eror code, but Java was designed differently using exceptions.


There is a new style of pattern available, and fits in with the "all asynchronous" nature that you might see in languages such as JavaScript.

A lot of my code looks like this nowadays :-)

public class Class1 {

    public interface Callback {
       void setData(String item1, String item2);
    }
    public void getThing(Callback callback) {
        callback.setData("a", "b");
    }
}

public class Class2 {

    public void doWithThing(Class1 o) {
        o.getThing(new Class1.Callback() {
            public void setData(String item1, String item2) {
                ... do something with item 1 and item 2 ...
            }
        });
    }

}

No new objects to create and not that many extra classes since the interface is an inner class of the object.

This is what makes Swift so awesome. The code can look like this:

o.getThing({ item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
});

And since the only argument is the block, even this:

o.getThing { item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
};

Java needs work to make callback laden code a lot easier to read.


I felt myself the need to return multiple values. And I was looking for a "pair" or "tuple" value. But after that, I've seen how I use the return type:

// scala
tuple(0)
tuple(1)

What 0 and 1 means and in which order? I think it is better to be explicit about what they mean. Create a small static class inside the object containing the method.

Just an example that comes into my mind. Maybe not the best:

public class SomeClass {
    
    public TimeInterval getValability(Voucher voucher) {
        .....
    }
    
    //value objects should be immutable
    public static class TimeInterval {
        public final LocalDate startDate;
        public final LocalDate endDate;
        private TimeInterval(LocalDate startDate, LocalDate endDate) {
            this.startDate = startDate;
            this.endDate = endDate;
        }
    }

}

then the person reading the code understand the result of the function:

TimeInterval interval = someClassInstance.getValability(voucher);
if(interval.startDate ......

instead of:

// from https://www.javatuples.org/
Pair interval = someClassInstance.getValability(voucher);
if(interval.getValue0() ......

I don't know your use case, but maybe your function is doing two things (Single Responsibility Principle)?

Edited:

Or maybe this example that I've found in my code will be more realistic:

@AllArgsConstructor
@Getter
public static class ResponseStatus {
    private final boolean isFailed;
    private final String failureReason;
}

with usage:

if (responseStatus.isFailed()) {
    customerHttpResponse.setAsFailed();
    customerHttpResponse.setResponseBody(responseStatus.getFailureReason());
    .....
}

In that way the client code is easier to read in my opinion.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号