47

我有一个具有泛型方法的抽象类,我想通过用特定类型替换泛型参数来覆盖泛型方法。所以在伪代码中我有以下内容:

public abstract class GetAndParse {
  public SomeClass var;

  public abstract <T extends AnotherClass> void getAndParse(T... args);
}

public class Implementor extends GetAndParse {
  // some field declarations

  // some method declarations

  @Override
  public <SpecificClass> void getAndParse(SpecificClass... args) {
    // method body making use of args
  }
}

但由于某种原因,我不允许这样做?我是在犯某种语法错误还是不允许这种继承和覆盖?具体来说,我收到一个错误,@Override因为 Eclipse IDE 不断提醒我实施getAndParse.

这就是我希望上面的代码如何工作。在我的代码的其他地方,有一个方法需要实现的对象实例,GetAndParse这特别意味着它们有一个getAndParse我可以使用的方法。当我调用getAndParse那个实例时,编译器会检查我是否T以正确的方式使用了特定的实例,所以特别是T应该扩展AnotherClass并且应该是SpecificClass.

4

6 回答 6

39

我们这里有两种不同的方法,每个方法都有单独的类型参数。

public abstract <T extends AnotherClass> void getAndParse(Args... args);

这是一个具有名为 T 的类型参数并以 为界的方法AnotherClass,这意味着允许 的每个子类型AnotherClass作为类型参数。

public <SpecificClass> void getAndParse(Args... args)

这是一个具有名为 的类型参数的方法,其SpecificClass边界为Object(意味着每种类型都允许作为类型参数)。你真的想要这个吗?

里面使用的是类型参数Args吗?我认为问题会在那里。


的意思

public abstract <T extends AnotherClass> void getAndParse(T... args);

是方法的调用者可以决定使用哪个类型参数来调用该方法,只要这是AnotherClass. 这意味着实际上可以使用任何类型的对象调用该方法AnotherClass

由于调用者可以决定类型参数,因此您不能在子类中将参数类型缩小到SpecificClass- 这不是方法的实现,而是另一个具有相同名称的方法(重载)。

也许你想要这样的东西:

public abstract class GetAndParse<T extends AnotherClass> {
  public SomeClass var;

  public abstract void getAndParse(T... args);
}

public class Implementor extends GetAndParse<SpecificClass> {
  // some field declarations

  // some method declarations

  @Override
  public void getAndParse(SpecificClass... args) {
    // method body making use of args
  }
}

现在该getAndParse方法实现了父类的方法。

于 2011-03-18T01:45:08.683 回答
19

由于 Java 泛型中称为“擦除”的概念,您会看到此问题。Java 使用“擦除”来支持向后兼容性。即不使用泛型的Java 代码。

擦除过程:
编译器将首先进行类型检查,然后它将尽可能删除(擦除)所有类型参数,并在必要时插入 TypeCasting。

例子:

public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);

会变成

public abstract void getAndParse(AnotherClass paramAnotherClass);

在“Implementor.java”类中,

编码

public <SpecificClass> void getAndParse(T paramAnotherClass)

会变成

public void getAndParse(SpecificClass paramAnotherClass){  }

编译器会看到你没有正确实现抽象方法。抽象方法和实现方法之间存在类型不匹配。这就是您看到错误的原因。

更多详细信息可以在这里找到。 http://today.java.net/pub/a/today/2003/12/02/explorations.html

于 2011-03-18T01:26:57.230 回答
2

您不能覆盖特定类型 T 因为实际上(如果您愿意,可以在字节码级别)getAndParse由于类型擦除而只有一种方法(请参阅其他答案):

public abstract void getAndParse(AnotherClass... args); // (1)

对于每种类型的 T,都使用相同的方法。

你可以重载它(我认为):

public void getAndParse(SpecificClass... args); // (2)

但这不会是与 (1) ant 不同的方法,它不会被通用代码调用:

T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass
于 2011-03-18T01:54:21.447 回答
1

不,它无效。如果有GetAndParse引用的人用不同的扩展类调用它会发生什么AnotherClass

于 2011-03-18T00:44:21.823 回答
1

当有人引用类型 GetAndParse 并尝试调用 getAndParse 方法时,这将成为无稽之谈。如果 Cat 和 Dog 扩展了 AnotherClass。我应该期望能够使用 Cat 或 Dog 调用 GetAndParse#getAndParse。但是实现试图限制它并降低它的兼容性!

于 2011-03-18T00:45:12.520 回答
0

静态方法不能覆盖

class Vehicle{
static void park(int location){
    System.out.println("Vehicle parking..");
}}

class Car extends  Vehicle{
@Override //error
void park(int location) { //error
    System.out.println("Car Parking..");
}}

私有方法不能覆盖

class Vehicle{
private void park(int location){
    System.out.println("Vehicle parking..");
}
void callPark(){
    park(100);
}}

class Car extends  Vehicle{
//@Override
void park(int location) {
    System.out.println("Car Parking..");
}}

class Demo {
public static void main(String[] args) {
    Vehicle v1=new Car();
   v1.callPark();
}}

最终方法无法覆盖

class Vehicle{
final void park(int location){
    System.out.println("Vehicle parking..");
}}

class Car extends  Vehicle{
//@Override
void park(int location) { //error
    System.out.println("Car Parking..");
}}
于 2018-10-25T18:30:26.280 回答