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

我试过这个,并从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); } 

然后我有testing用例:

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

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

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

是。 如果用一个带有编译时typesString的参数调用它,编译器就知道它不能是一个String[] ,所以它将它包装在一个string数组中。 所以这:

 String x = null; testNull(x); 

相当于:

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

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

但是,直接在方法调用中使用null String[] ,可直接转换为String[] ,因此不执行换行。

从JLS第15.12.4.2节 :

如果被调用的方法是一个variablesarity方法m,它必然有n> 0个forms参数。 m的最后forms参数对于某个T必然具有typesT [],并且必须用k≥0实际参数expression式调用m。

如果用k≠n实际参数expression式调用m,或者如果用k = n个实际参数expression式调用m,并且第k个参数expression式的types与T []不是兼容的 ,则参数列表(e1,…,en-1,en,…,ek)被评估为(e1,…,en-1,new | T [] | {en,… ,ek}),其中| T [] | 表示T []的删除(第4.6节)。

(强调我的)

我强调的一点是,为什么只有在参数的编译时types是String而不是nulltypes的时候才会发生包装。