在java中重写varargs

在java中重写varargs,java,overriding,variadic-functions,Java,Overriding,Variadic Functions,我试图回答另一个问题,这让我问了自己的问题。我做了一些研究,但找不到关于上述主题的任何信息 我有一个抽象类Character,它有一个下面用varargs参数定义的抽象方法 public abstract class Character { public abstract void doSomething(int... values); } 我的印象是,任何扩展这个类的类都可以用任意数量的参数重写这个方法 // 1st example public class Player extend

我试图回答另一个问题,这让我问了自己的问题。我做了一些研究,但找不到关于上述主题的任何信息

我有一个抽象类
Character
,它有一个下面用varargs参数定义的抽象方法

public abstract class Character {
   public abstract void doSomething(int... values);
}
我的印象是,任何扩展这个类的类都可以用任意数量的参数重写这个方法

// 1st example
public class Player extends Character { 
   @Override
   public void doSomething(int x, int y) { // Two params - do something }
}

// 2nd example 
public class NPC extends Character {
   @Override
   public void doSomething() { // No params - do something }
}
但是上述两个例子都导致了编译时错误。我想知道我错过了什么?上述情况是否可能发生


非常感谢您的帮助。

Java中的变量参数函数是一个纯粹的编译器技巧:当您声明这样的方法时

public abstract void doSomething(int... values);
public abstract void doSomething(int[] values);
编译器创建了这样一个方法

public abstract void doSomething(int... values);
public abstract void doSomething(int[] values);
并为自己做一个“心理笔记”,让您可以使用任意数量的整数参数调用
doSomething
。调用时,编译器将列出的参数包装到数组中,并将该数组传递给
doSomething
的实现

至于用一个采用固定数量参数的实现来重写这种方法的能力,这是不可能的:如果Java允许(它不允许),程序员将能够创建违反其扩展的抽象类接口的类层次结构。在第一种情况下,
Player
将无法处理此呼叫:

Character player = new Player(); // Allowed
player.doSomething(1, 2, 3, 4, 5); // What happens to 3, 4, and 5?
player.doSomething(1); // What value do we pass for y?
NPC
也会有同样的问题

可以使用采用数组的方法重写变量参数方法:

@Override
void doSomething(int[] values) {
    ...
}

Java中的变量参数函数是一个纯粹的编译器技巧:当您声明这样的方法时

public abstract void doSomething(int... values);
public abstract void doSomething(int[] values);
编译器创建了这样一个方法

public abstract void doSomething(int... values);
public abstract void doSomething(int[] values);
并为自己做一个“心理笔记”,让您可以使用任意数量的整数参数调用
doSomething
。调用时,编译器将列出的参数包装到数组中,并将该数组传递给
doSomething
的实现

至于用一个采用固定数量参数的实现来重写这种方法的能力,这是不可能的:如果Java允许(它不允许),程序员将能够创建违反其扩展的抽象类接口的类层次结构。在第一种情况下,
Player
将无法处理此呼叫:

Character player = new Player(); // Allowed
player.doSomething(1, 2, 3, 4, 5); // What happens to 3, 4, and 5?
player.doSomething(1); // What value do we pass for y?
NPC
也会有同样的问题

可以使用采用数组的方法重写变量参数方法:

@Override
void doSomething(int[] values) {
    ...
}

这是因为您正在重载该方法,而不是重写。要覆盖,您需要有完全相同的参数,这里是varargs->int。。。或数组->int[]


您可以在这里看到两者之间的区别:

这是因为您正在重载方法,而不是重写。要覆盖,您需要有完全相同的参数,这里是varargs->int。。。或数组->int[]


您可以在这里看到两者之间的区别:

我认为您对
抽象方法的概念完全错误。当一个类将另一个
抽象
类子类化时,它应该提供基类的
抽象
方法的具体实现

因此,当您声明如下方法时:

abstractvoiddosomething(int-somethint)

子类化类必须为具有相同签名的方法提供具体实现。除此之外的任何内容都被视为无效的方法声明,从而导致您看到的编译错误

我认为您最好看看解释抽象类和方法正确用法的文档


我认为你对
抽象方法的概念完全错了。当一个类将另一个
抽象
类子类化时,它应该提供基类的
抽象
方法的具体实现

因此,当您声明如下方法时:

abstractvoiddosomething(int-somethint)

子类化类必须为具有相同签名的方法提供具体实现。除此之外的任何内容都被视为无效的方法声明,从而导致您看到的编译错误

我认为您最好看看解释抽象类和方法正确用法的文档


我的印象是,任何扩展此类的类都可以用任意数量的参数覆盖此方法为什么?因为它可以用任意数量的参数调用,对吗?我的印象是,任何扩展此类的类都可以用任意数量的参数覆盖此方法为什么?因为它可以调用任何数量的参数对吗?@NicholasK绝对-您可以使用
void doSomething(int[]值)覆盖它而且,如果我使用
varargs
将方法抽象化,也没有什么帮助,对吗?因为如果最终必须被int类型的数组覆盖,那么最终我并没有真正实现任何目标。@NicholasK在抽象类中使其变为vararg是有用的,因为它允许调用方在通过抽象类类型的变量调用时调用参数数量可变的方法,例如,
Character player=new player()
而不是
player player=new player()
@NicholasK查看演示链接。单击顶部的“fork”,然后将
Character.doSomething
方法替换为
abstract void doSomething(int[]x)单击[运行]并查看将发生什么()。这是因为在基类的签名中使用
int..
也会启用对派生类的vararg调用。@NicholasK绝对-您可以使用
void doSomething(int[]值)覆盖它而且,如果我使用
varargs
将方法抽象化,也没有什么帮助,对吗?因为如果最终我没有取得任何成就