Résumé de la mise en œuvre des arguments par défaut en Java

Java n'a pas de ** fonctionnalité d'argument par défaut **, j'ai donc résumé une implémentation alternative.

TL;DR Je pense qu'il n'y a pas de problème s'il est mis en œuvre avec la politique suivante.

Nombre d'arguments que vous souhaitez définir par défaut Solution
~ 4 Surcharge
5 ~ Modèle de constructeur

Quel est l'argument par défaut

L'argument par défaut dans cet article est si la valeur n'est pas définie comme argument réel lors de l'appel de la méthode. Au lieu de cela, c'est un mécanisme pour initialiser avec la valeur par défaut. (Je pense que c'est une syntaxe qui est principalement introduite dans les langues modernes)

Voici un exemple des arguments par défaut écrits en Groovy.

def foo(a = 0, b = "undefined") {
    println "a = $a, b = $b"
}

foo(23, "hoge")  // => a = 23, b = hoge
foo()            // => a = 0, b = undefined

Comment implémenter en Java

1. Surcharge | Si le nombre d'arguments par défaut est petit

Vous pouvez facilement l'implémenter avec le modèle que vous voyez le plus souvent.

    static void foo(int a, String b) {
        System.out.println("a = " + a + ", b = " + b);
    }

    static void foo(int a) { foo(a, "undefined"); } //Seul l'argument b est l'argument par défaut
    static void foo(String b) { foo(0, b); }        //Seul l'argument a est l'argument par défaut
    static void foo() { foo(0, "undefined"); }      //Argument a,Les deux b sont des arguments par défaut

    public static void main(String[] args) {
        foo(23, "hoge");    // => a = 23, b = hoge
        foo(23);            // => a = 23, b = undefined
        foo("hoge");        // => a = 0, b = hoge
        foo();              // => a = 0, b = undefined
    }

Dans l'exemple, les arguments déclarés dans foo (int a, String b) sont de types différents, donc La surcharge vous permet de définir des valeurs par défaut pour tous les arguments. Si les arguments a et b sont du même type, il n'est pas possible de déclarer "argument par défaut uniquement pour l'argument a" et "argument par défaut uniquement pour l'argument b" en même temps. Dans ce cas, il n'y a pas d'autre choix que de l'implémenter avec le modèle Builder décrit plus loin ou en passant Null.

(Supplément) Argument de longueur variable | Si l'argument formel du type tableau n'est pas spécifié, la valeur par défaut du tableau vide est entrée.

La partie qui devient un argument de longueur variable a une restriction selon laquelle elle est le dernier des arguments de méthode, Si rien n'est spécifié dans le dernier argument, un tableau vide (longueur = 0) sera passé automatiquement. Par conséquent, dans de tels cas, il n'est pas nécessaire de surcharger.

    static void foo(String a, int... b) {
        int bSum = IntStream.of(b).sum();

        System.out.println("a = " + a + ", sum = " + bSum);
    }

    public static void main(String[] args) {
        foo("hoge", 23, 42);  // => a = hoge, sum = 65
        foo("hoge");          // => a = hoge, sum = 0
    }

2. Modèle de constructeur | Peut être utilisé de différentes manières. Cependant, le problème de la création d'une classe est ...

Outre la surcharge, il existe un modèle couramment utilisé qui utilise le modèle Builder pour définir les arguments par défaut. La surcharge est agréable car vous pouvez facilement définir la valeur par défaut, mais si le nombre d'arguments devient important Le code sera plus facile à lire si vous le remplacez par le modèle Builder. Selon la règle de SonarQube, il est souhaitable que le nombre d'arguments soit de 4 ou moins comme seuil. Java: Methods should not have too many parameters | SonarQube - Rules

Dans l'exemple, il est écrit pour définir la valeur par défaut dans le modèle Builder pour la méthode avec deux arguments.

import lombok.Builder;
import lombok.Value;

public class BuilderPattern {
    
    static void foo(Foo foo) {
        System.out.println("foo = " + foo);
    }
    
    public static void main(String[] args) {
        var specifiedFoo = Foo.builder().a(23).b("hoge").build();
        var defaultFoo = Foo.builder().build();
        foo(specifiedFoo);  // => foo = Foo(a=23, b=hoge)
        foo(defaultFoo);    // => foo = Foo(a=0, b=undefined)
    }
}

@Value
@Builder
class Foo {
    @Builder.Default
    Integer a = 0;
    @Builder.Default
    String b = "undefined";
}

(Supplément) Type de carte | Si vous faites cela, veuillez utiliser Builder

Vous pouvez faire la même chose avec le modèle Builder avec Map, mais si vous voulez le faire, je pense qu'il est préférable de l'écrire avec Builder.

    static void foo(Map<Foo, Object> params) {
        var a = (int) params.getOrDefault(Foo.A, 0);
        var b = (String) params.getOrDefault(Foo.B, "undefined");
        System.out.println("a = " + a + ", b = " + b);
    }

    public static void main(String[] args) {
        foo(Map.of(Foo.A, 23, Foo.B, "hoge"));  // => a = 23, b = hoge
        foo(Map.of());                          // => a = 0, b = undefined
    }

    enum Foo {
        A, B
    }

3. Pass Null | Lorsque l'argument pour définir la valeur par défaut est uniquement le premier ou le second

Comme je l'ai écrit dans l'explication de la surcharge, lorsque les arguments déclarés sont du même type, Dans certains cas, il n'était pas possible de définir une valeur par défaut pour chaque argument. La solution de contournement consiste à définir une valeur par défaut dans la méthode. Cependant, il n'est pas possible de déterminer quelle variable a la valeur par défaut en se basant uniquement sur la signature de la méthode. Les utilisateurs de méthode doivent regarder Javadoc ou l'implémentation de la méthode, qui est un modèle qu'ils ne veulent pas beaucoup utiliser.

    static void foo(String a, Integer b, Integer c) {
        b = Objects.requireNonNullElse(b, 0);
        c = Objects.requireNonNullElse(c, 0);
        System.out.println("a = " + a + ", b = " + b + ", c = " + c);
    }

    public static void main(String[] args) {
        foo("hoge", 23, 42);      // => a = hoge, b = 23, c = 42
        foo("hoge", null, null);  // => a = hoge, b = 0, c = 0
    }

(Supplément) Type optionnel | Non. Zettai.

En tant que problème avec le modèle de passage nul mentionné ci-dessus "Il n'est pas possible de déterminer quelle variable a la valeur par défaut en se basant uniquement sur la signature de la méthode." Il est facile de se demander, "Eh bien, peut-être que le type facultatif peut être utilisé?", Mais cela semble être assez critiqué. Parce que le type facultatif est un mécanisme pour indiquer à l'appelant que la valeur renvoyée à l'origine par la méthode peut être nulle. Si vous utilisez le type facultatif pour l'argument, le code devient plus redondant et le nombre de codes sans signification augmente. Par conséquent, le style d'écriture suivant est strictement interdit.

    static void foo(String a, Optional<Integer> bOpt) {
        var b = bOpt.orElse(0);
        System.out.println("a = " + a + ", b = " + b);
    }

    public static void main(String[] args) {
        foo("hoge", Optional.of(23));    // => a = hoge, b = 23
        foo("hoge", Optional.empty());   // => a = hoge, b = 0
        foo("hoge", null);               // => NullPointerException
    }

Les références

Java optional parameters | Stack Overflow Java: Methods should not have too many parameters | SonarQube - Rules Why should Java 8's Optional not be used in arguments | Stack Overflow

Recommended Posts

Résumé de la mise en œuvre des arguments par défaut en Java
Comment implémenter le calcul de la date en Java
[java] Résumé de la gestion des caractères
Résumé de l'écriture des arguments d'annotation
Comment appliquer les conventions de codage en Java
[Java] [Maven3] Résumé de l'utilisation de Maven3
Résumé de la sélection des éléments dans Selenium
[java] Résumé de la gestion des chaînes de caractères
[Java] Résumé de la façon d'omettre les expressions lambda
[Java] Comment implémenter le multithreading
Résumé de l'API de communication Java (1) Comment utiliser Socket
Résumé de l'API de communication Java (3) Comment utiliser SocketChannel
Résumé de l'API de communication Java (2) Comment utiliser HttpUrlConnection
Comment apprendre JAVA en 7 jours
Comment utiliser les classes en Java?
Comment nommer des variables en Java
Essayez d'implémenter Yuma en Java
Comment concaténer des chaînes avec Java
Comment implémenter l'affichage sur une seule ligne de TextView dans le développement Android
Comment dériver le dernier jour du mois en Java
Résumé de l'utilisation du jeu de proxy dans IE lors de la connexion avec Java
Comment créer un résumé de calendrier Java
Comment implémenter la fonctionnalité de recherche dans Rails
Prise en charge multilingue de Java Comment utiliser les paramètres régionaux
Essayez d'implémenter l'ajout n-aire en Java
[Webpacker] Résumé de l'installation de Bootstrap et jQuery dans Rails 6.0
Comment implémenter un travail qui utilise l'API Java dans JobScheduler
Comment faire une conversion de base en Java
Comment intégrer Janus Graph dans Java
Comment obtenir la date avec Java
Comment implémenter la fonctionnalité de classement dans Rails
Comment implémenter le traitement asynchrone dans Outsystems
Comment obtenir la longueur d'un fichier audio avec Java
Comment incrémenter la valeur de Map sur une ligne en Java
[Java] Passer des arguments au constructeur dans Mockito / Définir l'appel par défaut à la méthode à callRealMethod
Comment trouver le nombre total de pages lors de la pagination en Java
Comment afficher une page Web en Java
Comment obtenir une classe depuis Element en Java
Comment masquer les champs nuls en réponse en Java
Comment implémenter une fonctionnalité similaire dans Rails
Comment utiliser JQuery dans Rails 6 js.erb
Comment implémenter le verrouillage optimiste dans l'API REST
Comment résoudre les problèmes d'expression en Java
Comment écrire Java String # getBytes dans Kotlin?
Comment implémenter la pagination dans GraphQL (pour ruby)
Résumé du support Java 2018
Réflexion: Comment utiliser une interface fonctionnelle pour vos propres fonctions (java)
[Java] Comment obtenir l'URL de la source de transition
Comment implémenter UICollectionView avec du code uniquement dans Swift
Comment appeler des fonctions en bloc avec la réflexion Java
Comment créer un environnement Java en seulement 3 secondes
[Java] Comment omettre le constructeur privé dans Lombok
Comment implémenter la connexion invité en 5 minutes sur le portefeuille de rails
Comment implémenter une fonctionnalité intéressante dans Ajax avec Rails
J'ai essayé d'implémenter la notification push Firebase en Java
Comment écrire Scala du point de vue de Java
[Java] Types de commentaires et comment les rédiger