我有界面:
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
的定义中,两个泛型类型没有相互关联。这可能不是您想要的。
您在这里遇到的是两个通用类匹配的特殊情况(Long
和Cat
定义中的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
必须将String
与Long
进行比较。这是正确的做法,但这有点违反直觉。因为getById
的ID实际上是DogDAO
,所以具有Long
参数的Dog
的Long
方法更有意义。
如果要将两种类型结合在一起,可以将GenericDAO
类定义为:public abstract class GenericDAO<T extends Identifable<S>, S>
您仍然必须指定第二个参数,但是至少编译器可以帮助您确保类型匹配。