Java泛型,需要解释

4

有几个简单的测试用例类:

public interface ListCriteria<T> {
  // some stuff here
}

public class UserListCriteria implements ListCriteria<User> {
 // implementation
}

public interface Editor<T> {
  // sample method 1
  List<T> listObjectsTest1(ListCriteria<T> criteria);
  // sample method 2
  <L extends ListCriteria<T>> List<T> listObjectsTest2(L criteria);
}

这里有一个Editor的实现,Java认为它没有提供必要的实现来满足两个示例方法:

public class UserEditor implements Editor<User> {

  @Override
  public List<User> listObjectsTest1(UserListCriteria criteria) {
    //
  }

  @Override
  public List<User> listObjectsTest2(UserListCriteria criteria) {
    //
  }
}

两种方法的实现都是错误的。问题在于为什么,尤其是对于后一种方法。 当然,我可以使用interface Editor<T, L extends ListCriteria<T>>来解决此问题,但我不想这样做,我想要理解为什么我不能在此处使用方法级别的泛型。

2个回答

2

你所遇到的错误与泛型无关,因为你实现了方法但使用的类型与接口规定的不同。

Editor 接口定义了:

List<T> listObjectsTest1(ListCriteria<T> criteria);

因此,在您的情况下,UserEditor 必须实现。
public List<User> listObjectsTest1(ListCriteria<User> criteria) {

不要混淆参数类型和参数的泛型类型。接口Editor强制实现了ListCriteria类型。 ListCriteria的泛型类型是T,并且T可以由子类进行绑定,例如:implements ListCriteria<User>。这就是我说“你得到的错误与泛型无关”的意思。
我猜你想要的是:
public interface Editor<C, T extends ListCriteria<C>> {
    List<C> listObjectsTest1(T criteria);
}

然后,UserEditor可以实现为:

public class UserEditor implements Editor<User, UserListCriteria> {

   public List<User> listObjectsTest1(UserListCriteria criteria) {
      return null;
   }
}

为什么?特别是对于后一种方法

Editor界面中的第二种方法。

  <L extends ListCriteria<T>> List<T> listObjectsTest2(L criteria);

这并不意味着您可以实现任何类型的L绑定。 UserEditor仍然必须实现。

public <L extends ListCriteria<User>> List<User> listObjectsTest2(L criteria) {
    return null;
}

这个方法定义了一个通用类型L,当客户端调用该方法时,将绑定该类型。 因此,您可以使用任何是ListCriteria<User>子类型的类型来调用该方法。


谢谢,我的理解是我可以覆盖返回类型,但不能覆盖方法参数,并且即使在运行时UserListCriteria完全适合,我也必须保持完全相同的参数签名。 - andbi

1
  1. 您的UserEditorlistObjectsTest1(UserListCriteria criteria)函数没有覆盖Editor<T>接口的listObjectsTest1(ListCriteria<T> criteria)函数,因为它们具有两个不同的签名,即参数类型实质上不同。

  2. 对于listObjectsTest2也是如此,它在接口中声明为:<L extends ListCriteria<T>> List<T> listObjectsTest2(L criteria);但您在UserEditor类中将其声明为:List<User> listObjectsTest2(UserListCriteria criteria)

因此,您需要更改签名为:

class UserEditor implements Editor<User> {


    @Override
    public List<User> listObjectsTest1(ListCriteria<User> criteria) {

    }

    @Override
    public <L extends ListCriteria<User>> List<User> listObjectsTest2(L criteria) {

    }
}

请阅读jls 8.4.8. 继承、覆盖和隐藏以获取更多详细信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接