不传递参数或为空时的 Java 3 点参数(可变参数)行为 [英] Java 3 dots parameter (varargs) behavior when passed no arguments or null
问题描述
我尝试了这个并从 JAVA 中得到了奇怪的行为,有人可以为我解释一下吗?
I tried this and get weird behavior from JAVA, can someone explain this for me?
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
}
问题是如果我直接用参数null
调用testNull()
,我会得到true
,但是如果调用callTestNull()
和 null
,它调用 testNull()
,它告诉我参数不是 null,而是空数组.
The question is if I call testNull()
directly with parameter null
, I will get true
back, but if call callTestNull()
with null
, which calls testNull()
, it tells me the parameter is not null, but empty array.
推荐答案
问题是如果我直接用参数null调用testNull(),我会得到true,但是如果用null调用callTestNull(),它调用testNull(),它告诉我参数不是null,而是空数组.
The question is if I call testNull() directly with parameter null, I will get true back, but if call callTestNull() with null, which calls testNull(), it tells me the parameter is not null, but empty array.
是的.如果你用一个编译时类型的String
参数调用它,编译器知道不能是一个String[]
,所以它将它包装在一个字符串数组中.所以这个:
Yes. If you call it with an argument with a compile-time type of String
, the compiler knows that can't be a String[]
, so it wraps it within a string array. So this:
String x = null;
testNull(x);
相当于:
String x = null;
testNull(new String[] { x });
此时,(误导性命名的)string
参数将具有非空值 - 相反,它将引用大小为 1 的数组,其唯一元素是空引用.
At this point, the (misleadingly-named) string
parameter will have a non-null value - instead, it will refer to an array of size 1 whose sole element is a null reference.
但是,当您在方法调用中直接使用 null
文字时,它可以直接转换为 String[]
,因此不会执行任何包装.
However, when you use the null
literal directly in the method call, that's directly convertible to String[]
, so no wrapping is performed.
如果被调用的方法是一个可变数量的方法 m,那么它必然有 n >0 形式参数.对于某些 T,m 的最终形参必须具有类型 T[],并且 m 必须使用 k ≥ 0 个实参表达式调用.
If the method being invoked is a variable arity method m, it necessarily has n > 0 formal parameters. The final formal parameter of m necessarily has type T[] for some T, and m is necessarily being invoked with k ≥ 0 actual argument expressions.
如果使用 k ≠ n 个实参表达式调用 m,或者,如果使用 k = n 个实参表达式调用 m 并且第 k 个实参表达式的类型与 T[],则参数列表 (e1, ..., en-1, en, ..., ek) 被评估为好像它被写成 (e1, ..., en-1, new |T[]| { en, ..., ek }), 其中 |T[]|表示 T[] 的擦除(第 4.6 节).
If m is being invoked with k ≠ n actual argument expressions, or, if m is being invoked with k = n actual argument expressions and the type of the k'th argument expression is not assignment compatible with T[], then the argument list (e1, ..., en-1, en, ..., ek) is evaluated as if it were written as (e1, ..., en-1, new |T[]| { en, ..., ek }), where |T[]| denotes the erasure (§4.6) of T[].
(强调我的.)
我强调的一点是当参数的编译时类型是 String
而不是 null 类型时,仅会发生包装.
The bit I've emphasized is why the wrapping only happens when the compile-time type of the argument is String
, not the null type.
这篇关于不传递参数或为空时的 Java 3 点参数(可变参数)行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!