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

Java 中间的变量参数列表作为具有不同数据类型的参数,java,variadic-functions,Java,Variadic Functions,我和瓦拉格斯一起工作,并了解到:- public void myMethod(String... args, int val){} 方法myMethod的变量参数类型字符串必须是 最后一个参数 如果两者都类似于字符串,那么给出的错误是相当大的,但在本例中,我将int设置为第二个参数,因此在运行时JVM可以检查参数的类型&可以区分为:- myMethod("HI", "HELLO", 9) 这难道不可行吗。我缺少的任何其他点是否会产生错误?错误消息是正确的。如果使用varargs,它必须是最后

我和瓦拉格斯一起工作,并了解到:-

public void myMethod(String... args, int val){}
方法myMethod的变量参数类型字符串必须是 最后一个参数

如果两者都类似于字符串,那么给出的错误是相当大的,但在本例中,我将int设置为第二个参数,因此在运行时JVM可以检查参数的类型&可以区分为:-

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

这难道不可行吗。我缺少的任何其他点是否会产生错误?

错误消息是正确的。如果使用varargs,它必须是最后一个参数。你可以说它能解决问题,但不会。只需交换参数的顺序。

错误消息是正确的。如果使用varargs,它必须是最后一个参数。你可以说它能解决问题,但不会。只需交换参数的顺序。

当您在随机位置使用vararg重载方法时,消除歧义将成为一场噩梦。。。更不用说多个vararg了。

当您用随机位置的vararg重载方法时,消除歧义将成为一场噩梦。。。更不用说多个变量。

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

LastFormalParameter标记是定义和允许varargs的地方

注意。。。。这是形式参数语法中唯一允许这样做的地方。FormalParameters不允许这样做


这在JLS中有规定。语言规范要求将其作为正式参数列表的一部分:

LastFormalParameter标记是定义和允许varargs的地方

注意。。。。这是形式参数语法中唯一允许这样做的地方。FormalParameters不允许这样做


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

区别必须由编译器来完成,因为varargs完全是一个编译器特性。它们被简单地转换为隐式数组构造函数。 您的示例在理论上是可行的,但限制条件非常苛刻:例如,在这种情况下,编译器很难看到第一个varargs参数的结尾

void foo(Object... objs, String... s)
foo("a", "b", "c")
另一个例子是:

void bar(int... ints, long... longs)
foo(1, 2, 3, 4)
您可能会争辩说int和long是不同的数据类型,但不幸的是,由于转换范围的扩大,在需要long的地方可以使用整数。另一个例子是拳击:

void baz(Object... objs, int... ints)
baz(1, 2, 3, 4)
int和Object没有直接关系,但int可以转换为Integer,Integer是Object的一个子类

重载的方法和varargs参数越多,情况就越复杂

有点技术性,但仍然相关:在字节码中,varargs不是参数属性,而是方法修饰符标志ACC_varargs。这意味着要么方法是可变的,最后一个参数是varargs,要么不是。 如果方法中确实需要varargs参数,请将其移动到最后一个位置。唯一不能这样做的情况是当您有多个varargs参数时,这是不可能的。 如果编译器允许您在声明端执行此操作而不出错,那么在使用站点上几乎不可能获得有用的错误。 字符串。。。与字符串[]相同,只是不需要在使用站点创建数组。您可以声明一个方法

void foo(String[] strings, int i)
并称之为

void foo({ "a", "b" }, 2)
只需再击两次键,并且没有varargs参数引入的所有挣扎


我已经在一个编译器上工作了一年多了,我也考虑过添加这个特性。然而,方法解析系统已经非常复杂,我决定包含自定义中缀和前缀运算符/方法以及命名和默认参数,这并没有让它变得更容易,而且多个varargs参数也不会使它变得更简单。

语言设计者之所以选择不允许这种情况,有很多原因:

区别必须由编译器来完成,因为varargs完全是一个编译器特性。它们被简单地转换为隐式数组构造函数。 您的示例在理论上是可行的,但限制条件非常苛刻:例如,在这种情况下,编译器很难看到第一个varargs参数的结尾

void foo(Object... objs, String... s)
foo("a", "b", "c")
另一个例子是:

void bar(int... ints, long... longs)
foo(1, 2, 3, 4)
您可能会争辩说int和long是不同的数据类型,但不幸的是,由于转换范围的扩大,在需要long的地方可以使用整数。另一个例子是拳击:

void baz(Object... objs, int... ints)
baz(1, 2, 3, 4)
int和Object没有直接关系,但int可以转换为Integer,Integer是Object的一个子类

重载的方法和varargs参数越多,情况就越复杂

有点技术性,但仍然相关:在字节码中,varargs不是参数属性b ut方法修改器标志ACC_VARARGS。这意味着要么方法是可变的,最后一个参数是varargs,要么不是。 如果方法中确实需要varargs参数,请将其移动到最后一个位置。唯一不能这样做的情况是当您有多个varargs参数时,这是不可能的。 如果编译器允许您在声明端执行此操作而不出错,那么在使用站点上几乎不可能获得有用的错误。 字符串。。。与字符串[]相同,只是不需要在使用站点创建数组。您可以声明一个方法

void foo(String[] strings, int i)
并称之为

void foo({ "a", "b" }, 2)
只需再击两次键,并且没有varargs参数引入的所有挣扎


我已经在一个编译器上工作了一年多了,我也考虑过添加这个特性。然而,方法解析系统已经非常复杂,我决定包含自定义中缀和前缀运算符/方法以及命名和默认参数并没有让它变得更容易,多个varargs参数也不会让它变得更容易。

是的,但实际上我想知道上述原因。好奇,它杀死了你,但实际上想知道上面的原因。好奇心,它杀死了汉克斯。非常感谢。清除了很多: