使用单个null参数调用Java varargs方法?
如果我有一个vararg Java方法使用单个null参数调用Java varargs方法?,null,language-design,java,variadic-functions,Null,Language Design,Java,Variadic Functions,如果我有一个vararg Java方法foo(Object…arg)并且我调用foo(null,null),那么arg[0]和arg[1]都是nulls。但是如果我调用foo(null),arg本身就是null。为什么会这样 我应该如何调用foo,使foo.length==1&&foo[0]==null为true?您需要对对象进行显式转换: foo((Object) null); 否则,将假定参数是varargs表示的整个数组。这是因为可以使用实际数组而不是一系列数组元素调用varargs方法
foo(Object…arg)
并且我调用foo(null,null)
,那么arg[0]
和arg[1]
都是null
s。但是如果我调用foo(null)
,arg
本身就是null。为什么会这样
我应该如何调用
foo
,使foo.length==1&&foo[0]==null
为true
?您需要对对象进行显式转换:
foo((Object) null);
否则,将假定参数是varargs表示的整个数组。这是因为可以使用实际数组而不是一系列数组元素调用varargs方法。当您单独为它提供不明确的null
时,它假定null
是一个对象[]
。将null
强制转换为对象将解决此问题。问题在于,当您使用文本null时,Java不知道它应该是什么类型。它可以是空对象,也可以是空对象数组。对于单个参数,它假定后者
你有两个选择。显式地将null强制转换为对象或使用强类型变量调用该方法。请参见下面的示例:
public class Temp{
public static void main(String[] args){
foo("a", "b", "c");
foo(null, null);
foo((Object)null);
Object bar = null;
foo(bar);
}
private static void foo(Object...args) {
System.out.println("foo called, args: " + asList(args));
}
}
输出:
foo called, args: [a, b, c]
foo called, args: [null, null]
foo called, args: [null]
foo called, args: [null]
用于说明这一点的测试用例:
带有vararg taking方法声明(恰好是静态的)的Java代码:
此Java代码(JUnit4测试用例)调用了上述内容(我们使用该测试用例不是为了测试任何东西,只是为了生成一些输出):
将此作为JUnit测试运行会产生:
sendNothing(): received 'x' is an array of size 0
sendNullWithNoCast(): received 'x' is null
sendNullWithCastToString(): received 'x' is an array of size 1
sendNullWithCastToArray(): received 'x' is null
sendOneValue(): received 'x' is an array of size 1
sendThreeValues(): received 'x' is an array of size 3
sendArray(): received 'x' is an array of size 3
将此作为JUnit测试运行会产生以下结果,与Java的区别用粗体突出显示
sendNothing(): received 'x' is an array of size 0
sendNullWithNoCast(): received 'x' is null
sendNullWithCastToString(): received 'x' is null
sendNullWithCastToArray(): received 'x' is null
sendOneValue(): received 'x' is an array of size 1
sendThreeValues(): received 'x' is an array of size 3
sendArray(): received 'x' is an array of size 3
sendNothing():收到的“x”是大小为0的数组
sendNullWithNoCast():收到的“x”为空
sendNullWithCastToString():收到的“x”为null
sendNullWithCastToArray():收到的“x”为null
sendOneValue():收到的“x”是大小为1的数组
sendThreeValues():收到的“x”是大小为3的数组
sendArray():收到的“x”是大小为3的数组
我更喜欢
foo(new Object[0]);
避免空指针异常
希望有帮助。方法重载解析的顺序是():
第一阶段执行重载解析,不允许装箱或取消装箱转换,也不允许使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段
这保证了在Java SE 5.0之前的Java编程语言中有效的任何调用都不会因为引入变量arity方法、隐式装箱和/或取消装箱而被认为是不明确的。然而,变量arity方法的声明(§8.4.1)可能会改变为给定方法调用表达式选择的方法,因为变量arity方法在第一阶段被视为固定arity方法。例如,在已经声明了m(对象)的类中声明m(对象…)会导致不再为某些调用表达式(例如m(null))选择m(对象),因为m(对象[])更具体
第二阶段执行重载解析,同时允许装箱和取消装箱,但仍然禁止使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段
这确保了如果方法通过固定arity方法调用适用,则永远不会通过变量arity方法调用选择该方法
第三阶段允许重载与变量arity方法、装箱和取消装箱相结合
foo(null)
在第一阶段将foo(Object…arg)
与arg=null
匹配arg[0]=null
将是第三个阶段,这永远不会发生。Oops,这里也一样……抱歉,午夜。好吧,如果它是vararg方法,为什么不直接像foo()
?@BrainStorm.exe那样调用它呢?你的答案应该被标记为答案。谢谢。如果您在示例中列出了asList
方法及其用途,将对其他人有所帮助。@ArunKumarasList()
是从java.util.Arrays
类静态导入的。我只是认为这是显而易见的。虽然现在我在考虑它,但我可能应该只使用Arrays.toString()
,因为它转换为列表的唯一原因是它打印得很漂亮。这还考虑了调用不带参数的变量函数
import org.junit.Test
class GroovySender {
@Test
void sendNothing() {
System.out << "sendNothing(): " << JavaReceiver.receive() << "\n"
}
@Test
void sendNullWithNoCast() {
System.out << "sendNullWithNoCast(): " << JavaReceiver.receive(null) << "\n"
}
@Test
void sendNullWithCastToString() {
System.out << "sendNullWithCastToString(): " << JavaReceiver.receive((String)null) << "\n"
}
@Test
void sendNullWithCastToArray() {
System.out << "sendNullWithCastToArray(): " << JavaReceiver.receive((String[])null) << "\n"
}
@Test
void sendOneValue() {
System.out << "sendOneValue(): " + JavaReceiver.receive("a") << "\n"
}
@Test
void sendThreeValues() {
System.out << "sendThreeValues(): " + JavaReceiver.receive("a", "b", "c") << "\n"
}
@Test
void sendArray() {
System.out << "sendArray(): " + JavaReceiver.receive( ["a", "b", "c"] as String[] ) << "\n"
}
}
sendNothing(): received 'x' is an array of size 0
sendNullWithNoCast(): received 'x' is null
sendNullWithCastToString(): received 'x' is null
sendNullWithCastToArray(): received 'x' is null
sendOneValue(): received 'x' is an array of size 1
sendThreeValues(): received 'x' is an array of size 3
sendArray(): received 'x' is an array of size 3
foo(new Object[0]);