我尝试过这个,并从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(),它告诉我该参数不为空,但空数组。
testNull()
null
true
callTestNull()
问题是,如果我直接使用参数null调用testNull(),我会回来,但如果使用null调用callTestNull()调用了testNull(),它将告诉我参数不是null,而是空数组。
是。如果使用 编译时类型 为的参数调用它String,则编译器会知道它 不能 为String[],因此会将其包装在字符串数组中。所以这:
String
String[]
String x = null; testNull(x);
等效于:
String x = null; testNull(new String[] { x });
在这一点上,(具有误导性的)string参数将具有非null值-相反,它将引用大小为1的数组,其唯一元素是null引用。
string
但是,当您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节)。
如果要调用的方法是可变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类型 时才 进行换行。