4
votes

Utilisez Generic Supplier pour lever une exception non vérifiée

J'ai une liste de méthodes qui ont des arguments Supplier pour renvoyer des valeurs par défaut de différents types. Cependant, dans certains cas, je dois lancer une exception (non cochée) au lieu de valeurs.

Actuellement, je dois passer le lambda pour chaque définition de fonction mais je voudrais créer une instance fournisseur pour lancer l'exception et la réutiliser dans toutes les définitions de fonction.

J'ai le code suivant:

final static Supplier<?> NO_VALUE_FOUND = () -> {
        throw new UnsupportedOperationException();
    };


testInt("Key3", null, NO_VALUE_FOUND);
testBoolean("Key5", null,NO_VALUE_FOUND);

Mais je cherche à faire quelque chose comme:

    public static void main(String[] args)
    {

        testInt("Key1", 10, () -> 99);
        testInt("Key2", -19, () -> 0);
        testInt("Key3", null, () -> {
            throw new UnsupportedOperationException(); //repetition
        });
        testBoolean("Key4", true, () -> Boolean.FALSE);
        testBoolean("Key5", null, () -> {
            throw new UnsupportedOperationException();//repetition
        });
    }

    static void testInt(String key, Integer value, Supplier<Integer> defaultValue)
    {
        if (value != null)
            System.out.printf("Key : %s, Value : %d" + key, value);
        else
            System.out.printf("Key : %s, Value : %d" + key, defaultValue.get());
    }

    static void testBoolean(String key, Boolean value, Supplier<Boolean> defaultValue)
    {
        if (value != null)
            System.out.printf("Key : %s, Value : %d" + key, value);
        else
            System.out.printf("Key : %s, Value : %d" + key, defaultValue.get());
    }


2 commentaires

Et quelle est votre question? Quel est le problème avec la solution NO_VALUE_FOUND ?


@talex testBoolean par exemple lors du dernier appel, nécessiterait un argument de Suuplier


3 Réponses :


3
votes

Il vaudrait mieux que vous puissiez utiliser une implémentation plus générique comme:

final static Supplier<?> NO_VALUE_FOUND = () -> {
    throw new UnsupportedOperationException();
};

et l'utiliser ensuite comme:

public static void main(String[] args) {
    test("Key1", 10, () -> 99);
    test("Key2", -19, () -> 0);
    test("Key3", null, NO_VALUE_FOUND);
    test("Key4", true, () -> Boolean.FALSE);
    test("Key5", null, NO_VALUE_FOUND);
}

avec NO_VALUE_FOUND as:

static <T> void test(String key, T value, Supplier<T> defaultValue) {
    if (value != null)
        System.out.println("Key : " + key + " Value " + value); // note the change from printf since that had type specific placeholders
    else
        System.out.println("Key : " + key + " Value " + defaultValue.get());
}

Modifier (à partir des commentaires): si vous essayez de réussir votre NO_VALUE_FOUND de type Supplier> à votre fonction de test, et passer autre chose que la valeur littérale null comme deuxième argument, vous obtenir une erreur du compilateur.

Donc, pour résoudre les cas où toute autre valeur que null peut lancer une UnsupportedOperationException , utilisez une implémentation générique comme Suggéré dans la réponse MikeFHay.


3 commentaires

votre réponse n'aborde pas le problème de vérification de type d'OP. Si vous essayez de passer votre NO_VALUE_FOUND de type Supplier à votre fonction test , et passez autre chose que la valeur littérale null comme deuxième argument, vous obtiendrez une erreur du compilateur.


@MikeFHay C'est vrai, mais ce que j'ai compris de la question, c'est qu'il fallait renvoyer NO_VALUE_FOUND pour ces cas nuls uniquement.


Si vous savez au moment de l'écriture que le deuxième argument est nul, vous pouvez simplement appeler le fournisseur sans condition. Cette fonction n'est utile que si elle peut prendre une variable éventuellement nulle comme deuxième argument.



4
votes

Utilisez une méthode pour convertir la valeur NO_VALUE_FOUND dans le type approprié:

static <T>  Supplier<T> NO_VALUE_FOUND() {
    return (Supplier<T>) NO_VALUE_FOUND;
}

public static void main(String[] args) {
    testInt("Key3", null, NO_VALUE_FOUND());
    testBoolean("Key5", null,NO_VALUE_FOUND());
}


0 commentaires

4
votes

Similaire à la réponse de @ jon-hanson, vous pouvez définir une méthode qui renvoie directement le lambda, sans conversion nécessaire:

private <T> Supplier<T> noValueFound() {
    return () -> {
        throw new UnsupportedOperationException();
    };
}


0 commentaires