在 java 中覆盖可变参数

Overriding varargs in java

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

我有一个抽象 class Character,它有 1 个抽象方法,下面定义了可变参数

public abstract class Character {
   public abstract void doSomething(int... values);
}

我的印象是任何扩展此 class 的 class 都可以使用任意数量的参数覆盖此方法。

// 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);

并为自己创建一个 "mental note",让您可以根据需要使用任意数量的整数参数调用 doSomething。当您进行调用时,编译器会将您列出的参数包装到一个数组中,并将该数组传递给 doSomething.

的实现

至于使用固定数量参数的实现来覆盖此类方法的能力,这是不可能的:如果 Java 允许(但不允许),程序员将能够创建 class 层次结构,违反它们扩展的抽象 classes 的接口。在您的第一种情况下,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.

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

你可以在这里看到两者的区别:

我认为您对 abstract 方法的概念完全错误。当一个 class 子 class 是另一个 abstract class 时,它应该提供基本 class 的 abstract 方法的具体实现。

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

abstract void doSomething(int someInt);

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

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

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