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

Ank*_*gam 1 java variadic-functions

我正在和varargs一起工作并且知道: -

public void myMethod(String... args, int val){}
Run Code Online (Sandbox Code Playgroud)

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

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

myMethod("HI", "HELLO", 9)
Run Code Online (Sandbox Code Playgroud)

这不可行吗?我遗漏的任何其他要点都会产生错误?

Cla*_*oft 5

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

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

    void foo(Object... objs, String... s)
    foo("a", "b", "c")
    
    Run Code Online (Sandbox Code Playgroud)

    另一个例子是:

    void bar(int... ints, long... longs)
    foo(1, 2, 3, 4)
    
    Run Code Online (Sandbox Code Playgroud)

    你可以说,intlong不同的数据类型,但不幸的是它可以使用其中的整数long预计由于扩展转换.另一个例子涉及拳击:

    void baz(Object... objs, int... ints)
    baz(1, 2, 3, 4)
    
    Run Code Online (Sandbox Code Playgroud)

    int并且Object没有直接关联,但int可以转换为Integer,是子类Object.

  3. 你拥有的重载方法和varargs参数越多越复杂.

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

    void foo(String[] strings, int i)
    
    Run Code Online (Sandbox Code Playgroud)

    并称之为

    void foo({ "a", "b" }, 2)
    
    Run Code Online (Sandbox Code Playgroud)

    只需2次击键,而且没有varargs参数引入的所有挣扎.

我已经在JVM语言编译器上工作了一年多,我也考虑过添加这个功能.但是,方法解析系统已经非常复杂(我决定包含自定义infixprefix运算符/方法以及命名和默认参数不会使它变得更容易),并且多个varargs参数不会使它变得更容易.