How to write Java function that returns values of multiple data types?

后端 未结 11 1559
耶瑟儿~
耶瑟儿~ 2021-01-03 23:34

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 re

相关标签:
11条回答
  • 2021-01-03 23:59

    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.

    0 讨论(0)
  • 2021-01-04 00:02

    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.

    0 讨论(0)
  • 2021-01-04 00:04

    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!

    0 讨论(0)
  • 2021-01-04 00:08

    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.

    0 讨论(0)
  • 2021-01-04 00:10

    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.

    0 讨论(0)
提交回复
热议问题