代码之家  ›  专栏  ›  技术社区  ›  Ravi Gupta

为什么varargs应该是方法签名中的最后一个?

  •  20
  • Ravi Gupta  · 技术社区  · 14 年前

    如果我尝试写一个如下的方法

    public void someStuff(Object ... args, String a )
    

    someStuff方法的变量参数类型对象必须是最后一个参数。

    我不完全理解变量参数类型作为最后一种类型的要求。 任何输入都会有帮助。

    6 回复  |  直到 12 年前
        1
  •  22
  •   MSalters    14 年前

    它遵循C公约。C约定又是基于CPU架构的,CPU架构在堆栈上传递参数。第一个非vararg参数以stackframe中的固定偏移量结束。如果可以将vararg参数放在第一位,那么以下参数的堆栈偏移量将取决于传递的vararg参数数量。这将大大增加访问它们所需的代码量。

    在您的示例中,使用 String a 首先,从概念上讲,偏移量0与后面的vararg参数数量无关。但是 串a 最后,它可能在偏移量0、4、8、12等处-您必须进行计算 args.size * 4 每次你需要的时候 串a .

        2
  •  23
  •   Dimitar    7 年前

    变量参数必须是最后一个,这样编译器才能计算出哪个参数是哪个。

    “测试”、“测试”、“测试”、“测试”

    进入你的功能

    public void someStuff(Object ... args, String a)
    

    然而,当情况正好相反时

    public void someStuff(String a, Object ... args)
    

        3
  •  9
  •   Mark Byers    14 年前

    因为这会使语言变得不必要的复杂。想象一下,如果您还允许使用其他语法:

    public void someStuff(String a, Object ... args, String b)
    {
    }
    

    public void someStuff(String a, Object ... args, int b, Object ... args2)
    {
    }
    

    第二种语法表示一个字符串,后跟任意数量的Object类型的参数,后跟一个整数,后跟多个对象。当然,您可以设计一种可以接受类似内容的语言,但如果您还想指定args2必须至少包含一个元素,但args可以为空,该怎么办?为什么我们不能这样做呢?你 能够 设计这样一种语言。

    归根结底,你希望规则有多复杂?在这种情况下,他们选择了一个满足需求的简单选项。

        4
  •  3
  •   Daff    14 年前

    public void someStuff(Object ... args, String a )
    public void someStuff(String a, String b)
    

    编译器无法决定为某些东西选择什么方法(“Hello”、“Hello”)。

        5
  •  0
  •   Tendayi Mawushe    14 年前

    给定如何使用带有var args的方法,任何其他格式都可能导致歧义。让瓦拉格一家在最后 这会降低该功能的好处。

    public void varargsAreCool(String surname, String firstname, 
                               String... nicknames) {
        // some cool varargs logic
    }
    

    varargsAreCool("John", "Smith") John Smith 他没有绰号。像这样使用时 varargsAreCool("Andrew", "Jones", "The Drew", "Jonesy")

    public void varargsAreCool(String surname, String... nicknames,
                               String firstname) {
        // some cool varargs logic
    }
    

    当像这样使用时 Varagsarecool(“约翰”、“史密斯”) Smith varargsAreCool("John", new String[]{}, "Smith") 这是笨重的,有点违背了功能的目的。

    像这样使用时 varargsAreCool("Andrew", "The Drew", "Jonesy", "Jones") 是吗 The Drew, Jonesy and Jones 所有的昵称和姓氏都不见了?同样,这种歧义可以解决,但代价是额外的语法笨拙。