为什么可变参数应该是方法签名中的最后一个?

发布于 2024-08-19 10:28:44 字数 224 浏览 10 评论 0原文

如果我尝试编写如下方法,

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

我会收到此错误

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

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

If I try to write a method like below

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

I get this error

The variable argument type Object of the method someStuff must be the last parameter.

I don't fully understand the requirement of variable argument type to be the last.
Any inputs will be helpful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

音盲 2024-08-26 10:28:44

它遵循 C 约定。 C 约定又基于在堆栈上传递参数的 CPU 架构。第一个非 vararg 参数最终位于堆栈帧中的固定偏移处。如果您可以将 vararg 参数放在前面,则以下参数的堆栈偏移量将取决于您要传递的 vararg 参数的数量。这将使访问它们所需的代码量变得非常复杂。

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

It follows the C convention. The C convention in turn is based on CPU architectures which pass arguments on the stack. The first non-vararg arguments end up at a fixed offset in the stackframe. If you could put the vararg arguments first, the stack offset of the following arguments would depend on how many vararg parameters you would have passed. This would greatly complicate the amount of code needed to access them.

In your example, with String a first, it's conceptually at offset 0 independent how the number of vararg arguments that follow. But with String a last, it could be at offset 0, 4, 8, 12 etc - you'd have to calculate args.size * 4 everytime you needed String a.

鹿! 2024-08-26 10:28:44

变量参数必须是最后一个,以便编译器可以计算出哪个参数是哪个。

例如,假设您将

“test”、“test”、“test”、“test”

传递到函数中,

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

如果您希望 args 变量包含 3 或 4 个字符串,Java 将无法正常工作。在撰写本文时,这对您来说可能是显而易见的,但它是模糊的。

然而,当情况相反时,

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

Java 编译器看到第一个字符串,将其粘贴到“a”中,然后知道剩余的字符串可以安全地放入 args 中,并且变量上没有歧义。

The variable argument has to be the last so the compiler can work out which argument is which.

For example, say you pass

"test", "test", "test", "test"

into your function

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

Java cannot work out if you want the args variable to contain 3 or 4 strings. It may be obvious to you at the time of writing but it's ambiguous.

However, when it's the other way around

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

The Java compiler sees the first string, stick it into "a" and then knows that the remaining strings can be safely put into args and there is no ambiguity over the variables.

小镇女孩 2024-08-26 10:28:44

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

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

或者甚至:

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

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

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

Because that would make the language unnecessarily complex. Imagine if you also allowed other syntaxes:

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

Or even:

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

This second syntax means a string followed by any number of arguments of type Object, followed by an integer, followed by more objects. Sure you could design a language that could accept things like that, but what if you also wanted to specify that the args2 must contain at least one element, but args can be empty? Why can't we do that too? You could design such a language.

It boils down to, how complicated do you want the rules to be? In this case they chose a simple option that fulfils the needs.

一人独醉 2024-08-26 10:28:44

嗯,String 也是 Object 的实例,因此如果您使用可变参数,则可变参数数组必须是最后一个参数,因为编译器无法真正决定什么是args,你的字符串a是什么。将方法调用视为方法名称的元组和作为参数的对象列表。如果您有这样的两种方法:

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

编译器无法决定选择哪种方法
someStuff("Hello", "Hello")
如果您将 String a 作为第一个参数,它可以确定 someStuff(String, String)someStuff(String, Object) 更具体>。

Well, a String is also an instance of Object, so if you are using varargs, your vararg array has to be the last parameter because the compiler can't really decide what is args and what is your string a. Think of the method call as a tuple of method name and a list of objects which are your parameters. If you have two methods like so:

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

The compiler couldn't decide what method to choose for
someStuff("Hello", "Hello") .
If you put your String a as the first argument it can decide that someStuff(String, String) is more specific than someStuff(String, Object).

短叹 2024-08-26 10:28:44

鉴于如何使用带有 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
}

当像 varargsAreCool("John", "Smith") 使用时,Smith 是 John 的昵称还是姓氏?如果是他的姓氏,我如何表明他没有昵称?为此,您可能必须使用像 varargsAreCool("John", new String[]{}, "Smith") 这样的方法,该方法很笨拙,并且在某种程度上违背了该功能的目的。

像这样使用时, varargsAreCool("Andrew", "The Drew", "Jonesy", "Jones")The Drew、Jonesy 和 Jones 所有昵称和姓氏失踪了?同样,这种歧义可以得到解决,但代价是笨重的附加语法。

Given how a method with var args is used any other format could lead to ambiguities. Having the varargs last prevents possible ambiguities without requiring additional syntax to resolve the ambiguities which would lessen the benefit of the feature.

Consider the follow method declaration:

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

When used like varargsAreCool("John", "Smith") it is obvious that John Smith has no nicknames. When used like this varargsAreCool("Andrew", "Jones", "The Drew", "Jonesy").

Now consider the following invalid method declaration:

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

When used like varargsAreCool("John", "Smith") is Smith John's nickname or his surname? If it is his surname how do I indicate that he has no nicknames? To do this you would probably have to use the method like this varargsAreCool("John", new String[]{}, "Smith") which is clunky and somewhat defeats the purpose of the feature.

When used like this varargsAreCool("Andrew", "The Drew", "Jonesy", "Jones") are the The Drew, Jonesy and Jones all nicknames and the surname is missing? Again this ambiguity could be resolved but at the cost of clunky additional syntax.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文