web-dev-qa-db-fra.com

Comment écrire une fonction Java qui renvoie les valeurs de plusieurs types de données?

Par exemple, je souhaite créer une fonction pouvant renvoyer n'importe quel nombre (négatif, zéro ou positif).

Cependant, en fonction de certaines exceptions, j'aimerais que la fonction renvoie BooleanFALSE

Existe-t-il un moyen d'écrire une fonction pouvant renvoyer un int ou un Boolean?


Ok, donc cela a reçu beaucoup de réponses. Je comprends que j’aborde simplement le problème de manière incorrecte et que je devrais throw une sorte d’exception dans la méthode. Pour obtenir une meilleure réponse, je vais vous donner un exemple de code. S'il vous plaît ne vous moquez pas :)

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

  }

}
15
maček

Non, vous ne pouvez pas faire ça en Java.

Vous pouvez cependant renvoyer une Object. Et en renvoyant un objet, vous pouvez techniquement renvoyer une classe dérivée telle que Java.lang.Integer ou Java.lang.Boolean. Cependant, je ne pense pas que ce soit la meilleure idée.

13
Pablo Santa Cruz

Vous pouvez techniquement faire ceci:

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

Alors ce code compilerait:

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

Mais vous pouvez très certainement rencontrer des exceptions d'exécution si la méthode retourne un type incorrect. Vous devez également renvoyer des objets au lieu de primitives, car T est effacé dans Java.lang.Object, ce qui signifie que le type renvoyé doit étendre Object (c’est-à-dire un objet). L'exemple ci-dessus utilise l'autoboxing pour obtenir un type de retour primitif.

Je ne recommanderais certainement pas cette approche car, IMO, vous devez évaluer votre utilisation de la gestion des exceptions. Vous capturez des exceptions dans des cas exceptionnels si vous pouvez faire quelque chose avec cette exception (c'est-à-dire restaurer, persister, réessayer, etc.). Les exceptions sont une exception au flux de travail attendu, et n'en font pas partie.

11
hisdrewness

non. le mieux que vous puissiez faire est de retourner sur l'instance d'une classe qui gère tout ce que vous pourriez vouloir retourner.

quelque chose comme 

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

évidemment, vous devez jouer avec les noms ...

En outre, cela ressemble à une odeur de code. Vous pourrez peut-être supprimer le besoin de faire quelque chose comme ceci en qualifiant quel chemin vous voulez en dehors de votre fonction, puis appeler une fonction spécifique pour obtenir un booléen ou une fonction spécifique pour obtenir un int, selon la qualification. 

6
hvgotcodes

Ecrivez une fonction qui retourne une Object. Demandez-lui de renvoyer les objets wrapper Boolean ou Integer. Ensuite, utilisez instanceof pour déterminer lequel utiliser.

3
Alex Churchill

IEEE Floating Point

La plupart des langues gèrent votre exemple spécifique sans Exceptions ni types d'union, car le point flottant IEEE inclut une représentation pour NaN. En Java, utilisez 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);
}

Cela produit votre sortie exacte que vous vouliez:

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

Exceptions

Les exceptions sont The Old Java Way pour résoudre des problèmes similaires:

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

Voici votre code client pour une 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());
}

Types d'Union

Pour véritablement transmettre ou renvoyer des types non liés à une méthode, vous souhaitez que les types Union ne soient pas pris en charge par Java. Mais Paguro fournit Union Types que vous pouvez utiliser en Java comme ceci (en utilisant Ou):

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

Pour votre exemple spécifique, utilisez simplement Floating Point. Pour une solution plus générale, je trouve les types d'union plus utiles que les exceptions. Vous pouvez utiliser des types d'union comme arguments d'une méthode pouvant prendre deux entrées différentes sans interface ni ancêtre commune. Ils sont également plus favorables à la programmation fonctionnelle.

3
GlenPeterson

Non, une référence à un client.

Vous pouvez écrire un objet de réponse qui encapsule un booléen et un int et définir les valeurs en fonction de vos caprices.

Mais si j'étais un utilisateur, je penserais que votre conception est source de confusion.

1
duffymo

mon professeur a eu une idée géniale d'une méthode semblable à tryParse C # en 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
Munchyzzz

Cela peut ne pas être la meilleure solution en fonction de ce que vous voulez faire, mais un moyen simple de résoudre le problème consiste à demander à la fonction de renvoyer un entier ou une constante en dehors de la plage possible (telle que RETURNED_FALSE/TRUE) et de vérifier cela .

0
EscapeNT