Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用单个null参数调用Java varargs方法?_Null_Language Design_Java_Variadic Functions - Fatal编程技术网

使用单个null参数调用Java varargs方法?

使用单个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方法

如果我有一个vararg Java方法
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
    方法及其用途,将对其他人有所帮助。@ArunKumar
    asList()
    是从
    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]);