一尘不染

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

java

我尝试过这个,并从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(),它告诉我该参数不为空,但空数组。


阅读 210

收藏
2020-12-03

共1个答案

一尘不染

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

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

String x = null;
testNull(x);

等效于:

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

在这一点上,(具有误导性的)string参数将具有非null值-相反,它将引用大小为1的数组,其唯一元素是null引用。

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

JLS第15.12.4.2节开始

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

如果m用k≠n个实际参数表达式调用,或者m用k = n个实际参数表达式调用,并且第k个参数表达式 的类型与T []分配不兼容
,则参数列表(e1,…,en-1,en,…,ek)的计算方式就像(e1,…,en-1,new | T [] | {en,…
,ek}),其中| T [] | 表示T []的擦除(第4.6节)。

(强调我的。)

我强调的一点是为什么 在参数的编译时类型为而String不是null类型 时才 进行换行。

2020-12-03