Java Generic of Another generic

Cic*_*chy 7 java generics dao

我有界面:

interface Identifable<T extends Serializable> {
      T getID();
}
Run Code Online (Sandbox Code Playgroud)

和实现这个的类:

public class Cat implements Identifable<Long> {
       public Long getID(){...};
}
Run Code Online (Sandbox Code Playgroud)

一切正常.至今.现在我想创建GenericDAO,为什么我不能创建它?:

public abstract GenericDAO<T extends Identifable<S>> {
    T getByID(S id);
}
Run Code Online (Sandbox Code Playgroud)

我只能声明我的GenericDAO:

public abstract GenericDAO<T extends Identifable, S> {
  T getById(S id);
}
Run Code Online (Sandbox Code Playgroud)

完整的课程:

public CatDAO extends GenericDAO<Cat, Long> {
      Cat getById(Long id);
}
Run Code Online (Sandbox Code Playgroud)

但我觉得它没用,因为我重复信息.我已经声明,Cat实现了Identifable <Long>,为什么我必须声明GenericDAO <Cat,Long>,而不仅仅是GenericDAO <Cat>?

luc*_*mon 4

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

此外,每个泛型类型都必须在声明中指定。如果您想要class GenericDAO<T extends Identifable<U>>,则必须将泛型类型声明 for 添加U到您的类声明中,如下所示(因为U这里实际上是泛型类型):

public abstract class GenericDAO<T extends Identifable<U>, U> 
Run Code Online (Sandbox Code Playgroud)

以下内容部分偏离主题,但您可能会发现它很有用。

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

这里有一个特殊情况,其中两个泛型匹配(和定义Long中的类型)。考虑有这些声明:CatCatDAO

public class Dog implements Identifable<Long>
public class DogDAO extends GenericDao<Dog, String>
Run Code Online (Sandbox Code Playgroud)

getById这将迫使您在方法中编写方法DogDAO

Dog getById(String id);
Run Code Online (Sandbox Code Playgroud)

您的getId方法返回Doga,Long因此您的getById方法 intDogDAO必须将Strings 与Longs 进行比较。这是正确的做法,但有点违反直觉。拥有一个带有参数getById的方法更有意义,因为s ID 实际上是s。DogDAOLongDogLong

如果要将这两种类型联系在一起,可以将GenericDAO类定义为:

public abstract class GenericDAO<T extends Identifable<S>, S>
Run Code Online (Sandbox Code Playgroud)

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