我有界面:

interface Identifable<T extends Serializable> {
      T getID();
}

和实现此目的的类:
public class Cat implements Identifable<Long> {
       public Long getID(){...};
}

一切正常。至今。现在我要创建GenericDAO,为什么不能创建它?:
public abstract GenericDAO<T extends Identifable<S>> {
    T getByID(S id);
}

我只能这样声明我的GenericDAO:
public abstract GenericDAO<T extends Identifable, S> {
  T getById(S id);
}

并完成类(class):
public CatDAO extends GenericDAO<Cat, Long> {
      Cat getById(Long id);
}

但是我认为这没用,因为我会重复信息。我已经声明过Cat实现了Identifable ,那么为什么我必须声明GenericDAO 而不仅仅是GenericDAO ?

最佳答案

在Java中,必须指定每个泛型类型。您可以不指定任何类型,但不能不指定任何类型。

此外,必须在声明中指定每种通用类型的。如果要使用class GenericDAO<T extends Identifable<U>>,则必须像这样将U的通用类型声明添加到类声明中(因为U实际上是此处的通用类型):

public abstract class GenericDAO<T extends Identifable<U>, U>

以下内容部分不合时宜,但您可能会发现它很有用。

我注意到,在您对GenericDAO的定义中,两个泛型类型没有相互关联。这可能不是您想要的。

您在这里遇到的是两个通用类匹配的特殊情况(LongCat定义中的CatDAO类型)。考虑使用以下声明:
public class Dog implements Identifable<Long>
public class DogDAO extends GenericDao<Dog, String>

这将迫使您在getById方法中编写DogDAO方法:
Dog getById(String id);

您在getId中的Dog方法返回一个Long,因此您的getById方法int DogDAO必须将StringLong进行比较。这是正确的做法,但这有点违反直觉。因为getById的ID实际上是DogDAO,所以具有Long参数的DogLong方法更有意义。

如果要将两种类型结合在一起,可以将GenericDAO类定义为:
public abstract class GenericDAO<T extends Identifable<S>, S>

您仍然必须指定第二个参数,但是至少编译器可以帮助您确保类型匹配。

08-16 19:03