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,而是空数组。
是。 如果用一个带有编译时types的String
的参数调用它,编译器就知道它不能是一个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的时候才会发生包装。