web-dev-qa-db-fra.com

Java Comportement du paramètre 3 points (varargs) lorsqu'il ne reçoit aucun argument ou null

J'ai essayé cela et j'ai obtenu un comportement bizarre de Java, quelqu'un peut-il expliquer cela pour moi?

boolean testNull(String... string) {
    if(string == null) {
        return true;
    } else {
        System.out.println(string.getClass());
        return false;
    }
}

boolean callTestNull(String s) {
    return testNull(s);
}

Ensuite, j'ai un cas de test:

    @Test
    public void test_cases() {
        assertTrue(instance.testNull(null)); // NULL
        assertFalse(instance.testNull()); // NOT NULL
        assertFalse(instance.callTestNull(null)); // NOT NULL
    }

La question est de savoir si j'appelle testNull() directement avec le paramètre null, je récupérerai true, mais si j'appelle callTestNull() avec null, qui appelle testNull(), il me dit que le paramètre n'est pas nul, mais un tableau vide.

54
Jaiwo99

La question est de savoir si j'appelle testNull () directement avec le paramètre null, je reviendrai vrai, mais si j'appelle callTestNull () avec null, qui appelle testNull (), il me dit que le paramètre n'est pas nul, mais un tableau vide.

Oui. Si vous l'appelez avec un argument avec un type de compilation de String, le compilateur sait que ne peut pas être un String[], il l'enveloppe donc dans un tableau de chaînes. Donc ça:

String x = null;
testNull(x);

est équivalent à:

String x = null;
testNull(new String[] { x });

À ce stade, le paramètre (nommé de manière trompeuse) string aura une valeur non nulle - à la place, il fera référence à un tableau de taille 1 dont le seul élément est une référence nulle.

Cependant, lorsque vous utilisez le littéral null directement dans l'appel de méthode, il est directement convertible en String[], donc aucun habillage n'est effectué.

De section JLS 15.12.4.2 :

Si la méthode invoquée est une méthode d'arité variable m, elle a nécessairement n> 0 paramètres formels. Le paramètre formel final de m a nécessairement le type T [] pour certains T, et m est nécessairement invoqué avec k ≥ 0 expressions d'argument réelles.

Si m est invoqué avec k ≠ n expressions d'argument réelles, ou, si m est invoqué avec k = n expressions d'argument réelles et que le type de la kième expression n'est pas compatible avec les affectations avec T [] , alors la liste d'arguments (e1, ..., en-1, en, ..., ek) est évaluée comme si elle était écrite comme (e1, .. ., en-1, nouveau | T [] | {en, ..., ek}), où | T [] | dénote l'effacement (§4.6) de T [].

(Je souligne.)

Le bit que j'ai souligné est la raison pour laquelle le wrapping seulement se produit lorsque le type de compilation de l'argument est String, pas le type null.

58
Jon Skeet