在Java中返回多个值的最佳实践?

时间:2013-05-17 12:38:54

标签: java function return

今天我在登录表单后面添加了额外的安全检查,以减缓暴力攻击。我有多个登录表单并且做了一个很好的易于调用的函数来完成所有检查,然后返回结果。

public static ValidateLoginResult validateLogin(HttpServletRequest request, String email, String password) {

问题是结果不是单个值,结果包括:

boolean ok
String errorMessage
boolean displayCaptcha

为此我创建了一个新类。一切正常。

但是我经常有一些方便的实用程序函数可以返回多个值,并且每次都为每次创建一个新类而开始发现它有点烦人。

有更好的方法可以返回多个值吗?还是我只是懒惰? :)

7 个答案:

答案 0 :(得分:16)

不,这种结构在Java中并不存在,但您可以查看可能符合您需求的JavaTuples library并提供一个非常优雅的解决方案。使用Triplet<Boolean, String, Boolean>

答案 1 :(得分:5)

不确定“最佳做法”,但务实的选择是返回Map<String, String>? E.g。

myMap.put("result", "success");
myMap.put("usernameConfirmed", "bigTom");

return myMap;

面对百万OO原则,可能会飞,但我听说你想避免结果类的扩散。

您也可以使用Map<String, Object>并对存​​储对象进行类型检查更严格:字符串,布尔值,日期等。

答案 2 :(得分:5)

您可以定义Pair<A, B>类和Triplet<A, B, C>类,这样可以解决在确保类型安全的同时返回2和3值的问题。在这种特殊情况下,签名可以是

public static boolean validateLogin(HttpServletRequest request,
            String email, String password, Pair<Message, Boolean> outputIfOk);

或者甚至更好,在servlet上下文中,设置一些记录良好的请求属性可能是有意义的。

如果您发现自己需要特殊的类来经常返回结果,那么您很可能会重构这些条款以共享共同的祖先(例如,有一个包含'ok'和'message'字段的RequestStatus)。

除此之外,是的,你是懒惰的 - 自定义条款总是比双人和三胞胎更自我记录。

答案 3 :(得分:4)

我无法想到一种更好,更清洁,更面向对象的方法,即从函数中返回多个值,而不是将它们封装在一个类中。

理想情况下,您想要返回的多个值在概念上都属于同一个类,因此以这种方式对它们进行分组是有意义的;如果他们不这样做,那么你应该在一些较小的函数中分解你的函数,这些函数返回函数本身之外所需的每个值。

据我所知,一些IDE还具有帮助在类中封装多个值的工具:例如,Eclipse具有Refactor --> Extract class...

答案 4 :(得分:1)

你可以返回一个Object []数组,java autoboxes,因此它更容易使用。如果只是短距离移交,为什么不呢。 Ofc风险,可能的阶级捣乱,零检查等

但它易于编写和使用。

然后再次快速创建一个静态内部类,如果你把它放在返回它的方法旁边,你也知道在哪里找到它(通常在原点附近)

答案 5 :(得分:0)

我可能只是自己去班级路线,但根据你希望函数返回的内容,你可以逃脱返回某种值的容器。

答案 6 :(得分:0)

这是我从另一个讨论中得到的一种可能的解决方案,并对其进行了增强。 它使用带有私有构造函数的公共内部类:

public class Test {
    // Internal storage unit for the two values:
    // 'name' and 'age'.
    private Pair<String, Integer> info;

    public Test() {
        // Empty default constructor.
    }

    /**
     * The two values are stored in the Test class.
     *
     * @param name
     * @param age
     */
    public void setInfo(String name, int age) {
        info = new Pair<>(name, age);
    }

    /**
     * The 'name' and 'age' values are returned in a
     * single object.
     *
     * @return Both values in a Pair object.
     */
    public Pair<String, Integer> getInfo() {
        return info;
    }

    /**
     *  This is an Inner Class for providing pseudo 'tuplet'
     *  as a 'get' return value.
     *
     * @param <F> first internally stored value.
     * @param <S> second internally stored value.
     */
    public class Pair<F, S> {

        public final F first;
        public final S second;

        // This constructor is private to prevent
        // it being instantiated outside its
        // intended environment.
        private Pair(F first, S second) {
            this.first = first;
            this.second = second;
        }

        @Override
        public String toString(){
            return first + ", " + second;
        }
    }

    /**
     * main method for testing of the class only.
     *
     * @param args
     */
    public static void main(String args[]) {
        Test test = new Test();

        test.setInfo("Peter Smith", 35);
        Test.Pair<String, Integer> pair = test.getInfo();

        System.out.println("name: " + pair.first);
        System.out.println("age: " + pair.second);
        System.out.println(pair.toString());
    }
}