传递无参数或null时的Java 3点参数(varargs)行为

时间:2013-07-17 14:39:39

标签: java variadic-functions ellipsis

我试过这个并从JAVA那里得到奇怪的行为,有人可以帮我解释一下吗?

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

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

然后我有测试用例:

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

问题是,如果我直接使用参数testNull()拨打null,我会返回true,但如果callTestNull()null通话,则会调用testNull() {{1}},它告诉我参数不是null,而是空数组。

1 个答案:

答案 0 :(得分:56)

  

问题是如果我直接使用参数null调用testNull(),我将返回true,但是如果调用callTestNull()并调用testNull(),它会告诉我参数不是null,而是空数组

是。如果使用带有编译时类型 String的参数调用它,则编译器知道不能String[],所以它将它包装在一个字符串数组中。所以这个:

String x = null;
testNull(x);

相当于:

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

此时,(误导性命名的)string参数将具有非空值 - 相反,它将引用大小为1的数组,其唯一元素为空引用。

但是,当您在方法调用中直接使用null文字时,它可以直接转换为String[],因此不会执行换行。

来自JLS section 15.12.4.2

  

如果被调用的方法是变量arity方法m,则它必然具有n> 0形式参数。对于某些T,m的最终形式参数必然具有类型T [],并且必须使用k≥0实际参数表达式调用m。

     

如果用k≠n实际参数表达式调用m,或者,如果用k = n实际参数表达式调用m,并且第k个参数表达式的类型不与T赋值兼容] ,然后对参数列表(e1,...,en-1,en,...,ek)进行评估,就好像它被写为(e1,...,en-1,new | T [] | {en,...,ek}),其中| T [] |表示T []的擦除(§4.6)。

(强调我的。)

我强调的一点是,当参数的编译时类型为String而不是null类型时,为什么只包