如何在Java中从一个方法返回多个值

3

我已经在Java中编写了一个方法,它返回两个值。第一个是结果的计数,类型为int;第二个是方法是否成功的布尔类型,true/false。

我该如何返回这两个值呢?只有当方法成功时才继续执行。

示例代码:

public static void main(String args[])
{
    int count = 0;
    boolean status = false;
    //count = retrieveData(); Current code working but captures only 1 values at a time i.e. Count not the status

    /* Expected Code

    if (status == true)  // where status and count is returned from retrieveData method
    {
        count = retrieveData();
        System.out.println("Status is true so can proceed");
    }

    else
        System.out.println("Status is not true so don't proceed");
    */
}





public static int retrieveData() throws  Exception 
    {

        boolean success = false;
        String query = "SELECT Count(1) FROM Account";
        int totalCount=0;
        ResultSet rsRetrieve = null;
            Statement stmt = null;
            stmt = conn.createStatement();
            rsRetrieve = stmt.executeQuery(query);
            while (rsRetrieve.next())
            {
                totalCount= rsRetrieve.getInt(1);
                System.out.println("totalCount : "+totalCount);
            }


        success = true;
        return totalCount; // current working code but returns only 1 value i.e. Count not status

        /*   Expected

        return success + totalCount

        */
    }

有一个返回 Map.Entry<K,V> 的选项,你可以使用 Integer 作为键,Boolean 作为值... - deHaar
你可以返回一个数组、一个映射,甚至是一个自定义类来保存所有需要返回的值。不幸的是,很少有编程语言能像 Golang 一样做到这一点。 - Luke
由于结果计数应为零或更多,因此当您想要指示操作失败时,只需返回负数即可。 - RealSkeptic
1
此外,它怎么可能不成功呢?如果出现异常,那么你就会抛出它(避免使用throws Exception来代替具体的异常)。是否有一种“不成功”的方式可以不抛出异常呢? - RealSkeptic
我已经投票支持重新开放这个问题,因为在这里返回多个值甚至不是必要的(也不是最佳实践)。 - Tim Biegeleisen
在您的特定情况下,我建议抛出异常而不是返回状态值。但一般来说,如果您想要做这样的事情,您有以下选项:(1)使用OptionalInt,其中失败条件会导致缺少值; (2)使用Integer,其中null值表示失败(优先使用OptionalInt,因为它更安全); (3)使用特殊的非有效值,例如当唯一有效值为正数时使用-1; (4)使用某种成对结构,例如Map.Entry - DodgyCodeException
6个回答

3

从方法中返回多个值有不同的方法,我使用的一些最佳方法包括:

1- 创建一个类来保存你想要返回的数据类型,例如你想要返回两个字符串,可以创建如下类:

public class myType {
            String a;
            String b;

            public String getA() {
                return a;
            }

            public void setA(String _a) {
                a = _a;
            }
            //And All other geter setters
        }

并将你的方法的返回类型设置为上述类。

2- 返回包含键值对的 Map
3- 创建接口并从中调用抽象方法以返回值(您必须在要接收这些值的类中实现该接口) 希望这能给您一个大致的想法来前进。


2
你可以按照以下方式创建自定义的Java对象:

创建一个自定义Java对象的方法如下

public class Result {

   private boolean success;
   private int totalResults;

   public Result(boolean success, int totalResults){
    this.success = success;
    this.totalResults = totalResults;
   }
   public boolean getSuccess(){
     return this.success;
   }

   public boolean getTotalResults(){
       return this.totalResults;
   }

}

1
我想使用 any[1] 来模拟指针作为输出。就像 C++ 中的 *p 和 C# 中的 out
boolean[] p_status = new boolean[1];
int count = retrieveData(p_status);
boolean status = p_status[0];

其他示例,通用:

public static void main(String[] args) throws JsonProcessingException {
    // I try to analysis the string, but don't want to create a new class
    var strs = "1,2,ABC,3,4,6,7,1,6,9,XYZ,3,6,3,7,9,2,5,9,ABC";

    // use any[1] as pointer
    int[] p_iStrCount = new int[1];
    // when facing eneric, it's a little different
    @SuppressWarnings("unchecked") HashMap<Integer, Integer>[] p_hmNum = new HashMap[1];

    // use pointer as parameters, so I can get multiple results out
    var hmStr = analysis(strs, p_iStrCount, p_hmNum);
    var iStrCount = p_iStrCount[0];
    var hmNum = p_hmNum[0];
}

// `strs` as input
// `pOut_iStrCount`, `pOut_hmNum`, `return` as output
// You can ignore the details of this method
static HashMap<String, Integer> analysis(@NotNull String strs, @Nullable int[] pOut_iStrCount, @Nullable HashMap<Integer, Integer>[] pOut_hmNum){

    var aryStr = StringUtils.split(strs, ",");
    var iStrCount = null != aryStr ? aryStr.length : 0;
    var hmStr = new HashMap<String, Integer>();
    var hmNum = new HashMap<Integer, Integer>();

    if(null != aryStr){
        for(String str : aryStr){
            hmStr.compute(str, (k,v)->(null == v ? 0 : v + 1));
            int num;
            try{
                num = Integer.parseInt(str);
            }catch (NumberFormatException ignore){
                continue;
            }
            hmNum.compute(num, (k,v)->(null == v ? 0 : v + 1));
        }
    }

    if(null != pOut_iStrCount){ pOut_iStrCount[1] = iStrCount; }
    if(null != pOut_hmNum){ pOut_hmNum[1] = hmNum; }

    return hmStr;
}

0

我建议坚持您当前的一般方法,而不是尝试从您的方法中返回两个信息。您的方法签名会抛出异常,处理此异常的一种可能方式是在出现问题时使您的方法抛出异常。否则,这意味着计数查询已运行,并且将返回某些计数。但是,您应该在JDBC代码周围放置try catch块:

public static int retrieveData(Connection conn) throws Exception {
    Statement stmt = null;
    int totalCount = 0;

    try {
        String query = "SELECT COUNT(*) FROM Account";

        ResultSet rsRetrieve;
        stmt = conn.createStatement();
        rsRetrieve = stmt.executeQuery(query);

        if (rsRetrieve.next()) {
            totalCount = rsRetrieve.getInt(1);
            System.out.println("totalCount : " + totalCount);
        }
    }
    catch (SQLException e) {
        System.out.println(e.getMessage());
        threw new Exception("something went wrong");
    }
    finally {
        if (stmt != null) {
            stmt.close();
        }

        if (conn != null) {
            conn.close();
        }

    }

    return totalCount;
}

因此,这里使用的模式是,如果出现问题,则没有计数,并且调用者会收到异常。否则,如果没有发生异常,则会返回一些计数。


我认为这段代码可能失败的唯一方式是当出现SQL异常(或某些意外的运行时错误)时。如果你捕获了它并没有再次抛出,那么你就错过了一个返回语句。另外,conn()是什么? - RealSkeptic
@RealSkeptic 感谢您成为如此怀疑者。我已经修复了那些错别字。是的,可能会有其他异常,但我们通常也不期望未经检查的异常(至少这是我的理解)。 - Tim Biegeleisen
1
我的观点是,无论如何捕获异常都没有意义,当然也不要用通用的“Exception”替换它。让它被抛出即可。当然,有时候用自定义异常来替换可能会有用,但我不鼓励初学者随意抛出“Exception”。 - RealSkeptic
我的观点是我们应该捕获异常,因为我们无论如何都需要一个“finally”块,而且除此之外,也许我们想要做一些自定义日志记录。 - Tim Biegeleisen
1
为什么finally块意味着你需要捕获异常?自定义日志是一件好事,但每个应用程序都有自己的日志需求,如果在调用者中有一个catch子句 - 这是问题的重点,区分成功和失败 - 最好在那里记录日志。无论如何,为什么不重新抛出原始异常并替换为不包含任何关于发生情况的信息的异常? - RealSkeptic

0

你不能直接这样做,但是你可以创建一个 bean 类来保存多个对象。

如果这是用于程序错误处理,你可能需要查看 Optional(标准)或 Either(vavr)来处理多个结果。


-1

你可以使用Java Pair

import javafx.util.Pair;

public Pair retrieveData(int a, int b) {
   return new Pair(a, b);
}

Pair p = retrieveData(1,2);
int a = p.getKey();     // 1
int b = p.getValue();   // 2

2
请注意,Java 11标准发行版不包含JavaFX。 - Federico klez Culloca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接