如何编写返回多种数据类型值的Java函数?

Posted

技术标签:

【中文标题】如何编写返回多种数据类型值的Java函数?【英文标题】:How to write Java function that returns values of multiple data types? 【发布时间】:2011-06-24 13:59:33 【问题描述】:

例如,我想创建一个可以返回任何数字(负数、零或正数)的函数。

但是,基于某些例外情况,我希望函数返回 Boolean FALSE

有没有办法编写一个可以返回intBoolean的函数?


好的,所以收到了很多回复。我知道我只是错误地解决了这个问题,我应该 throw 方法中的某种异常。为了得到更好的答案,我将提供一些示例代码。请不要开玩笑:)

public class Quad 

  public static void main (String[] args) 

    double a, b, c;

    a=1; b=-7; c=12;
    System.out.println("x = " + quadratic(a, b, c, 1));   // x = 4.0
    System.out.println("x = " + quadratic(a, b, c, -1));  // x = 3.0


    // "invalid" coefficients. Let's throw an exception here. How do we handle the exception?
    a=4; b=4; c=16;
    System.out.println("x = " + quadratic(a, b, c, 1));   // x = NaN
    System.out.println("x = " + quadratic(a, b, c, -1));  // x = NaN

  

  public static double quadratic(double a, double b, double c, int polarity) 

    double x = b*b - 4*a*c;

    // When x < 0, Math.sqrt(x) retruns NaN
    if (x < 0) 
      /*
        throw exception!
        I understand this code can be adjusted to accommodate 
        imaginary numbers, but for the sake of this example,
        let's just have this function throw an exception and
        say the coefficients are invalid
      */
    

    return (-b + Math.sqrt(x) * polarity) / (2*a);

  


【问题讨论】:

你已经得到了很多答案,所以你可以看到它是可能的,但不是很好。我建议你解释一下你需要它做什么。然后你很可能会得到一个更好的解决方案。顺便说一句,异常也可以通过抛出异常来表示。返回 Boolean.FALSE 并且从不返回 Boolean.TRUE 是代码异味,请考虑返回 Integer 并返回 null 而不是 FALSE。 使用返回值是C风格的编程。并不是说这有什么问题,而是考虑例外情况。这就是它们的目的。 【参考方案1】:

不,你不能在 Java 中这样做。

不过,您可以返回 Object。通过返回一个对象,您可以在技术上返回一个派生类,例如java.lang.Integerjava.lang.Boolean。但是,我认为这不是最好的主意。

【讨论】:

【参考方案2】:

技术上你可以这样做:

public <T> T doWork()

   if(codition)
   
      return (T) new Integer(1);
   
   else
   
      return (T) Boolean.FALSE;
   

然后这段代码将编译:

int x = doWork(); // the condition evaluates to true
boolean test = doWork();

但如果方法返回错误的类型,您肯定会遇到运行时异常。您还必须返回对象而不是原语,因为 T 被擦除为 java.lang.Object,这意味着返回的类型必须扩展 Object(即是一个对象)。上面的示例使用自动装箱来实现原始返回类型。

我当然不会推荐这种方法,因为 IMO 您需要评估您对异常处理的使用。如果您可以对异常执行某些操作(即恢复、持久化、重试等),则可以在异常情况下捕获异常。异常是预期工作流的异常,而不是其中的一部分。

【讨论】:

【参考方案3】:

没有。你能做的最好的就是返回一个类的实例来处理你可能想要返回的所有事情。

类似

public class ReturnObj 
   public bool yesno; // yes or no
   public int val; // for int values
   public String mode; // mode describing what you returned, which the caller will need to understand.

显然,你需要玩弄名字....

此外,这似乎是一种代码异味。您可以通过限定函数外部所需的路径来消除执行此类操作的需要,然后根据限定条件调用特定函数以获取布尔值或特定函数以获取 int。

【讨论】:

你应该使用Enum,而不是String【参考方案4】:

IEEE 浮点数

大多数语言将处理您的特定示例而没有异常或联合类型,因为 IEEE 浮点包含 NaN 的表示。在 Java 中,使用 Double.NaN:

public static double quadratic(double a, double b, double c, int polarity) 
    double x = b*b - 4*a*c;

    // When x < 0, Math.sqrt(x) retruns NaN
    if (x < 0) 
        return Double.NaN;
    
    return (-b + Math.sqrt(x) * polarity) / (2*a);

这会产生您想要的确切输出:

x = 4.0
x = 3.0
x = NaN
x = NaN

例外情况

异常是解决类似问题的旧 Java 方法:

public static double quadratic(double a, double b, double c, int polarity) 
    double x = b*b - 4*a*c;
    // When x < 0, Math.sqrt(x) returns NaN
    if (x < 0) 
        throw new Exception("NaN")
    
    return (-b + Math.sqrt(x) * polarity) / (2*a);

这是您的异常客户端代码。

a=1; b=-7; c=12;

// x = 4.0
try 
    System.out.println("x = " + quadratic(a, b, c, 1));
 catch (Exception iae) 
    System.out.println("Oopsie: " + iae.getMessage());


// x = 3.0
try 
    System.out.println("x = " + quadratic(a, b, c, -1));
 catch (Exception iae) 
    System.out.println("Oopsie: " + iae.getMessage());


// "invalid" coefficients.
a=4; b=4; c=16;

// Oopsie: NaN
try 
    System.out.println("x = " + quadratic(a, b, c, 1));
 catch (Exception iae) 
    System.out.println("Oopsie: " + iae.getMessage());


// Oopsie: NaN
try 
    System.out.println("x = " + quadratic(a, b, c, -1));
 catch (Exception iae) 
    System.out.println("Oopsie: " + iae.getMessage());

联合类型

要真正向方法传递或返回不相关的类型,您需要 Java 并不真正支持的 Union 类型。但是 Paguro 提供了Union Types,您可以像这样在 Java 中使用它(使用 Or):

public static Or<Double,String> quadratic(double a, double b,
                                          double c, int polarity) 
    double x = b*b - 4*a*c;

    // When x < 0, Math.sqrt(x) retruns NaN
    if (x < 0) 
        return Or.bad("NaN");
    
    return Or.good((-b + Math.sqrt(x) * polarity) / (2*a));


@Test public void testQuadradic() 
    double a, b, c;
    a=1; b=-7; c=12;

    // x = Good(4.0)
    System.out.println("x = " + quadratic(a, b, c, 1));

    // x = 3.0
    System.out.println(
            (String) quadratic(a, b, c, -1)
                    .match(good -> "x = " + good,
                           bad -> "Oopsie: " + bad));

    // "invalid" coefficients.
    a=4; b=4; c=16;

    // x = Bad("NaN")
    System.out.println("x = " + quadratic(a, b, c, 1));

    // Oopsie: NaN
    System.out.println(
            (String) quadratic(a, b, c, -1)
                    .match(good -> "x = " + good,
                           bad -> "Oopsie: " + bad));

结论

对于您的具体示例,只需使用浮点数。对于更通用的解决方案,我发现联合类型比异常更有用。您可以使用联合类型作为方法的参数,该方法可能采用两个没有公共接口或祖先的不同输入。它们对函数式编程也更友好。

【讨论】:

【参考方案5】:

编写一个返回Object 的函数。让它返回 BooleanInteger 包装器对象。然后使用 instanceof 来确定使用哪个。

【讨论】:

【参考方案6】:

不,一个返回给客户的参考。

您可以编写一个将布尔值和整数封装在一起的响应对象,并根据自己的想法设置值。

但如果我是用户,我会认为你的设计令人困惑。

【讨论】:

【参考方案7】:

我的老师对 java 中类似 tryParse C# 的方法有一个很酷的想法,希望对您有所帮助

import java.util.Scanner;

public class Program 
    static Scanner scanner = new Scanner(System.in);
    public static void main(String[] args) 
        System.out.println("Enter number");
        String input = scanner.next();
        int[] num =0;
        if(tryParse(input,num))
            System.out.println(num[0] * num[0]);
    
    static boolean tryParse(String inputString,int[] outputInt)
        try
            outputInt[0] = Integer.parseInt(inputString);
            return true;
        catch(Exception e)
            return false;
        
    

【讨论】:

【参考方案8】:

这可能不是最佳解决方案,具体取决于您要执行的操作,但解决问题的一种简单方法可能是让函数返回可能范围之外的 int 或常量(例如 RETURNED_FALSE/TRUE)和检查一下。

【讨论】:

【参考方案9】:

绝对!在您的情况下,由于返回值可以是正数、0、负数或假,因此最好的返回值可能是 JSONObject。在您的代码中,您将添加此导入:

import org.json.JSONObject;

在函数中:

JSONObject retval = new JSONObject();
double x = b*b - 4*a*c;
if(x < 0)
    retval.put("result", false);

else
    retval.put("result", x);

您可能还可以向 retval 添加另一个键:值对以包含结果类型,以帮助在调用函数中检查它。

【讨论】:

【参考方案10】:

我会说这是可能的。但不是直接的。

我没有完成问题中给出的程序。我知道这是一个旧帖子,所以我正在回答这个问题。可能会帮助某人。

将您的值添加到如下图所示。用它的钥匙拿到它!

public static HashMap returnAnyType()
    String x = "This";
    int a = 9;

    HashMap<String, Object> myMap = new HashMap();
    myMap.put("stringVal", x);
    myMap.put("intVal", a);
    return myMap;


String theStringFromTheMap = (String) returnAnyType().get("stringVal");
int theIntFromTheMap = (Integer) returnAnyType().get("intVal");

System.out.println("String : " + theStringFromTheMap + " is great !");   
System.out.println("Integer: " + Math.addExact(theIntFromTheMap, 10));

输出(都从同一个方法返回):

字符串:这太棒了! 整数:19

注意: 这不是一个好习惯。但有时在需要时会有所帮助!

【讨论】:

我没有投反对票,但我确实有几个问题/cmets: 1. 您应该为HashMap 指定类型参数。 2.钥匙是怎么做的?【参考方案11】:

inout 参数仅适用于可以变异的对象。对于 String inout 参数,传入 StringBuilders 而不是 Strings,然后 replace() 他们的值。

【讨论】:

以上是关于如何编写返回多种数据类型值的Java函数?的主要内容,如果未能解决你的问题,请参考以下文章

易语言如何编写一个DLL文件

CXF编写的客户端调用XFire编写的服务端,返回值为null,没有报错

通过在 android/java 中由 JavaScript 编写的函数在 FCM 中的同一应用程序中制作多种类型的通知

编写一个sort函数,它用于对任何类型的数组进行排序

如何在 func swift 4 中编写关于比较布尔值的 func

函数作为swift4中的类型