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

发布于 2024-10-16 20:50:44 字数 1333 浏览 5 评论 0 原文

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

但是,基于某些异常,我希望函数返回 Boolean FALSE

有没有办法编写一个可以返回 int 的函数> 一个布尔值


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

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);

  }

}

For example, I want to create a function that can return any number (negative, zero, or positive).

However, based on certain exceptions, I'd like the function to return Boolean FALSE

Is there a way to write a function that can return an int or a Boolean?


Ok, so this has received a lot of responses. I understand I'm simply approaching the problem incorrectly and I should throw some sort of Exception in the method. To get a better answer, I'm going to provide some example code. Please don't make fun :)

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);

  }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

如梦亦如幻 2024-10-23 20:50:44

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

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

No, you can't do that in Java.

You could return an Object though. And by returning an object you could technically return a derived class such as java.lang.Integer or java.lang.Boolean. However, I don't think it's the best idea.

柠檬色的秋千 2024-10-23 20:50:44

从技术上讲,您可以这样做:

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(即是一个对象)。上面的示例使用自动装箱来实现原始返回类型。

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

You could technically do this:

public <T> T doWork()
{
   if(codition)
   {
      return (T) new Integer(1);
   }
   else
   {
      return (T) Boolean.FALSE;
   }
}

Then this code would compile:

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

But you could most certainly encounter runtime exceptions if the method returns the wrong type. You also must return objects instead of primitives because T is erased to java.lang.Object, which means the returned type must extend Object (i.e. be an object). The above example makes use of autoboxing to achieve a primitive return type.

I certainly wouldn't recommend this approach because IMO you need to evaluate your use of exception handling. You catch exceptions in exceptional cases if you can do something with that exception (i.e. recover, persist, retry, etc.). Exceptions are an exception to the expected workflow, not a part of it.

说好的呢 2024-10-23 20:50:44

不。您能做的最好的事情就是返回一个处理您可能想要返回的所有内容的类的实例。

显然

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,具体取决于限定。

no. the best you can do is return on instance of a class that handles all the things you might want to return.

something like

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.
}

obviously, you need to play with the names....

Also, this seems like a code smell. You might be able to remove the need to do something like this by qualifying what path you want outside of your function, and then call a specific function to get a boolean or a specific function to get an int, depending on the qualification.

心不设防 2024-10-23 20:50:44

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 并不真正支持的联合类型。但 Paguro 提供了 Union 类型 您可以像这样在 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));
}

结论

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

IEEE Floating Point

Most languages will handle your specific example without Exceptions or union types because IEEE floating point includes a representation for NaN. In Java, use 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);
}

That produces your exact output that you wanted:

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

Exceptions

Exceptions are The Old Java Way of solving similar problems:

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);
}

Here's your client code for an Exception.

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());
}

Union Types

To truly pass or return unrelated types to or from a method, you want Union types which Java does not really support. But Paguro provides Union Types which you can use in Java like this (using 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));
}

Conclusion

For your specific example, just use Floating Point. For a more general solution, I find union types more useful than Exceptions. You can use union types as arguments to a method that might take two different inputs which have no common interface or ancestor. They are also more friendly to Functional Programming.

黯然 2024-10-23 20:50:44

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

Write a function that returns an Object. Have it either return the Boolean or Integer wrapper objects. Then use instanceof to figure out which to use.

十年不长 2024-10-23 20:50:44

不,是向客户返回一份参考信息。

您可以编写一个将 boolean 和 int 封装在一起的响应对象,并根据您的想法设置值。

但如果我是用户,我会认为你的设计很混乱。

No, one return reference to a customer.

You can write a response object that encapsulates a boolean and an int together and set the values according to your whim.

But if I was a user I'd think your design was confusing.

混浊又暗下来 2024-10-23 20:50:44

我的老师有一个很酷的想法,在 java 中使用类似于 C# 的 tryParse 方法希望它有帮助

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;
        }
    }
}

my teacher had a cool idea for a tryParse C# like method in java hope it helps

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;
        }
    }
}
清浅ˋ旧时光 2024-10-23 20:50:44

这可能不是最好的解决方案,具体取决于您想要做什么,但解决问题的一个简单方法可能是让函数返回一个 int 或一个超出可能范围的常量(例如 RETURNED_FALSE/TRUE)并检查它。

This may not be the best solution depending on what you want to do, but an easy way to solve the problem might be to have the function return an int or a constant outside the possible range (such as RETURNED_FALSE/TRUE) and check for that.

我爱人 2024-10-23 20:50:44

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

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

将您的值添加到如下所示的地图中。并用钥匙获取它!

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));

输出(两者均从同一方法返回):

String:这太棒了!
整数:19

注意:
这不是一个好的做法。但有时在需要的时候它会有所帮助!

I would say it is possible. But not directly.

I haven't gone through the program given in the question. I am answering this knowing this is an old post. Might help someone.

Add your values to a Map like below. And get it with its key!

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));

Output (both are returned from same method):

String : This is great!
Integer: 19

Note:
This is not a good practice. But it helps sometimes when it is needed!

感情废物 2024-10-23 20:50:44

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

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 添加另一个键:值对以包含结果类型,以帮助在调用函数中检查它。

Absolutely! In your case, since the return values can be positive, 0, negative, or false, probably the best return value would be a JSONObject. In your code, you would add this import:

import org.json.JSONObject;

and in the function:

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

You potentially could also add another key:value pair to the retval to include the result type to help with checking it in the calling function.

寂寞花火° 2024-10-23 20:50:44

今天早上早些时候我也想知道同样的事情,我做了一个很好的小解决方法,在我的情况下运行良好。

我想构建一个扩展 AWT JPanel 的表类,以便我可以将其作为组件添加到 JFrame 中。它需要接受一个ArrayList>来存储所有表数据(本质上是行列表)。但是,该值有时是 String,有时是 double,有时是 int。因此,我创建了一个名为 Value 的类,它有 3 个构造函数、一个私有枚举 Type 和一个名为 getContents() 的返回方法。我的课程是这样安排的:

public class Value {
    private String string;
    private double decimal;
    private int number;
    private Type type;

    public Value(int i) {
        this.number = i;
        type = Type.NUMBER;
    }
    public Value(double d) {
        this.decimal = d;
        type = Type.DECIMAL;
    }
    public Value(String s) {
        this.string = s;
        type = Type.STRING;
    }

    public Object getContents() {
        switch(type) {
        case STRING:return string;
        case DECIMAL:return decimal;
        default:return number;
    }
}
private enum Type {
    STRING, DECIMAL, NUMBER
}

要使用它,我在我的 GopherTable 中使用了它(请忽略名称,它与软件的上下文相关)

public class GopherTable extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private ArrayList<ArrayList<Value>> rows;

    public GopherTable() {
        rows = new ArrayList<ArrayList<Value>>();
    }

    public void addRow(ArrayList<Value> items) {
        rows.add(items);
    }
}

这个解决方案在我的情况下完美运行,并且AFAIK不会冒犯很多人。有时,您所询问的解决方案并不是您正在寻求的解决方案。有关详细信息,请参阅此链接

I wondered this same thing earlier this morning, and I made a nice little workaround that functioned well in my circumstance.

I wanted to build a table class that extended the AWT JPanel, so that I could add it as a component to a JFrame. It would need to take in an ArrayList<ArrayList<some value>> that would store all of the tabledata (essentially a list of rows). The value, however, would sometimes be a String, sometimes a double, and sometimes an int. So I created a class called Value which has 3 constructors, a private enum Type, and a return method called getContents(). My class is arranged like so:

public class Value {
    private String string;
    private double decimal;
    private int number;
    private Type type;

    public Value(int i) {
        this.number = i;
        type = Type.NUMBER;
    }
    public Value(double d) {
        this.decimal = d;
        type = Type.DECIMAL;
    }
    public Value(String s) {
        this.string = s;
        type = Type.STRING;
    }

    public Object getContents() {
        switch(type) {
        case STRING:return string;
        case DECIMAL:return decimal;
        default:return number;
    }
}
private enum Type {
    STRING, DECIMAL, NUMBER
}

To use this, I've used it in my GopherTable (ignore the name please, it is relevant in the context of the software)

public class GopherTable extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private ArrayList<ArrayList<Value>> rows;

    public GopherTable() {
        rows = new ArrayList<ArrayList<Value>>();
    }

    public void addRow(ArrayList<Value> items) {
        rows.add(items);
    }
}

This solution worked perfectly in my case and AFAIK wouldn't offend very many people. Sometimes, the solution you are asking about is not the solution you are seeking. See this link for more on that.

や莫失莫忘 2024-10-23 20:50:44

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

inout parameters only work for objects that can be mutated. For String inout parameters, pass in StringBuilders instead of Strings, then replace() their values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文