在Java中重写varargs

时间:2018-08-23 18:03:24

标签: java override variadic-functions

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

我有一个抽象类Character,它有1个下面用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 }
}

但是以上两个示例都导致了编译时错误。我想知道我在这里想念什么?上述情况甚至可能吗?

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

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

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) {
    ...
}

Demo.

答案 1 :(得分:2)

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

您可以在此处看到两者之间的区别:https://stackoverflow.com/a/2469860/8923905

答案 2 :(得分:-1)

我认为您对abstract方法的概念全错了。当一个类对另一个abstract类进行子类化时,它应该提供基类的abstract方法的具体实现。

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

abstract void doSomething(int someInt);

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

我认为您最好看看说明正确使用抽象类和方法的文档。

https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html