作为具有不同数据类型的参数的Between之间的变量参数列表

时间:2015-07-28 14:20:21

标签: java variadic-functions

我正在使用varargs并且知道: -

public void myMethod(String... args, int val){}
  

myMethod方法的变量参数类型String必须是   最后一个参数。

如果两者都像String那样,错误的给定是相当的,但在这种情况下,我将int设置为第二个参数,因此在运行时JVM可以检查类型论证和可以区分如下: -

myMethod("HI", "HELLO", 9)

这不可行。我遗漏的任何其他方面都会产生错误?

4 个答案:

答案 0 :(得分:5)

语言设计师选择不允许这样做有很多原因:

  1. 必须由编译器进行区分,因为varargs完全是编译器功能。它们只是简单地转换为隐式数组构造函数。
  2. 您的示例在理论上可以解决,但限制会非常苛刻:例如,编译器很难看到第一个varargs参数在这种情况下结束的位置

    void foo(Object... objs, String... s)
    foo("a", "b", "c")
    

    另一个例子是:

    void bar(int... ints, long... longs)
    foo(1, 2, 3, 4)
    

    您可能认为intlong是不同的数据类型,但不幸的是,由于扩大转化次数,可能会使用预期long的整数。另一个例子涉及拳击:

    void baz(Object... objs, int... ints)
    baz(1, 2, 3, 4)
    

    intObject没有直接关系,但int可以转换为Integer,这是Object的子类。

  3. 您拥有的重载方法和变量参数越多越复杂。

  4. 有点技术性,但仍然相关:在字节码中,varargs不是参数属性,而是方法修饰符标志(ACC_VARARGS)。这意味着方法是可变参数(最后一个参数是varargs)或者它不是。
  5. 如果您的方法中确实需要varargs参数,请将其移至最后位置。你无法做到这一点的唯一情况是你有多个varargs参数,这是不可能的。
  6. 如果编译器允许你在声明端执行此操作而没有错误,那么在use-site上几乎不可能得到有用的错误。
  7. String...String[]相同,只是您不需要在使用地点创建数组。您可以声明方法

    void foo(String[] strings, int i)
    

    并将其命名为

    void foo({ "a", "b" }, 2)
    

    只有2次击键,没有varargs参数引入的所有挣扎。

  8. 我已经在JVM-language编译器上工作了一年多,我也考虑过添加这个功能。但是,方法解析系统已经极其复杂(我决定包含自定义infixprefix运算符/方法以及命名和默认参数无法实现任何更简单的方法,多个varargs参数都不会让它变得更容易。

答案 1 :(得分:0)

错误消息是正确的。如果你使用varargs,它必须是最后一个参数。你可以说它可以解决它,但事实并非如此。只需交换参数的顺序。

答案 2 :(得分:0)

当你在随机位置使用varargs重载方法时,消歧将成为一场噩梦...(不是说多个varargs)。

答案 3 :(得分:0)

这是在JLS section 8.4.1中指定的。语言规范要求将其作为形式参数列表的一部分:

FormalParameterList:
    ReceiverParameter 
    FormalParameters , LastFormalParameter 
    LastFormalParameter

LastFormalParameter令牌是定义和允许varargs的地方。

LastFormalParameter:
    {VariableModifier} UnannType {Annotation} ... VariableDeclaratorId 
    FormalParameter

注意...。这是正式参数语法中唯一允许这样做的地方。 FormalParameters没有这个限额。

FormalParameters:
    FormalParameter {, FormalParameter} 
    ReceiverParameter {, FormalParameter}