Как написать функцию Java, которая возвращает значения нескольких типов данных? - PullRequest
16 голосов
/ 10 февраля 2011

Например, я хочу создать функцию, которая может возвращать любое число (отрицательное, нулевое или положительное).

Однако, исходя из определенных исключений, я бы хотел, чтобы функция возвращала BooleanFALSE

Есть ли способ написать функцию, которая может возвращать int или a Boolean?


Хорошо, так что этополучил много ответов.Я понимаю, что просто неправильно подхожу к проблеме, и мне следует 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);

  }

}

Ответы [ 10 ]

13 голосов
/ 10 февраля 2011

Нет, вы не можете сделать это в Java.

Вы можете вернуть Object.И, возвращая объект, вы можете технически вернуть производный класс, такой как java.lang.Integer или java.lang.Boolean.Однако я не думаю, что это лучшая идея.

11 голосов
/ 10 февраля 2011

Технически вы можете сделать это:

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 вам нужно оценить, как вы используете обработку исключений. Вы исключаете исключения в исключительных случаях, если можете что-то сделать с этим исключением (т.е. восстановить, сохранить, повторить и т. Д.). Исключения составляют исключение для ожидаемого рабочего процесса, а не его часть.

6 голосов
/ 10 февраля 2011

нет.лучшее, что вы можете сделать, это вернуть экземпляр класса, который обрабатывает все, что вы, возможно, захотите вернуть.

что-то вроде

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

, очевидно, вам нужно поиграть с именами....

Кроме того, это похоже на запах кода.Возможно, вам удастся устранить необходимость делать что-то подобное, указав, какой путь вы хотите вне своей функции, а затем вызвать определенную функцию, чтобы получить логическое значение, или определенную функцию, чтобы получить целое число, в зависимости от квалификации.

4 голосов
/ 21 августа 2013

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

Типы объединения

Чтобы действительно передавать или возвращать несвязанные типы в или из метода,вам нужны типы Union, которые Java на самом деле не поддерживает.Но 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));
}

Заключение

Для вашего конкретного примера просто используйте Floating Point.Для более общего решения я считаю типы объединения более полезными, чем исключения.Вы можете использовать типы объединения в качестве аргументов для метода, который может принимать два разных входа, которые не имеют общего интерфейса или предка.Они также более дружественны к функциональному программированию.

3 голосов
/ 10 февраля 2011

Напишите функцию, которая возвращает Object. Пусть он вернет объекты-оболочки Boolean или Integer. Затем используйте instanceof, чтобы выяснить, какой из них использовать.

1 голос
/ 05 января 2012

У моего учителя была классная идея для метода tryParse C # в Java, надеюсь, он поможет

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;
        }
    }
}
1 голос
/ 10 февраля 2011

Нет, одна возвращаемая ссылка на клиента.

Вы можете написать объект ответа, который инкапсулирует логическое значение и целое число вместе, и установить значения в соответствии с вашей прихотью.

Но если ябыл пользователь, я думаю, ваш дизайн сбивал с толку.

0 голосов
/ 30 декабря 2015

Я бы сказал, что это возможно. Но не напрямую.

Я не прошел программу, указанную в вопросе. Я отвечаю на это, зная, что это старый пост. Может помочь кому-нибудь.

Добавьте свои значения на карту, как показано ниже. И возьми его своим ключом!

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 : This is great!
Integer: 19

Примечание:
Это не очень хорошая практика. Но иногда помогает, когда это необходимо!

0 голосов
/ 25 апреля 2012

параметры inout работают только для объектов, которые могут быть изменены.Для параметров String inout передайте StringBuilders вместо Strings, а затем замените () их значения.

0 голосов
/ 10 февраля 2011

Это может быть не лучшим решением в зависимости от того, что вы хотите сделать, но простой способ решения проблемы может состоять в том, чтобы функция возвращала int или константу вне возможного диапазона (например, RETURNED_FALSE / TRUE) ипроверьте это.

...