如何创建使用另一个通用Java接口键入的通用Java接口?
我们方法的目标是向现有的DAO和模型类引入接口。模型类由各种类型的资源ID标识,资源ID不仅仅是随机数,还包含语义和行为。因此,我们必须用对象而不是基元类型来表示资源ID 资源ID的当前方法:如何创建使用另一个通用Java接口键入的通用Java接口?,java,generics,design-patterns,persistence,dao,Java,Generics,Design Patterns,Persistence,Dao,我们方法的目标是向现有的DAO和模型类引入接口。模型类由各种类型的资源ID标识,资源ID不仅仅是随机数,还包含语义和行为。因此,我们必须用对象而不是基元类型来表示资源ID 资源ID的当前方法: 接口资源ID{ T get(); } 类UserId实现了ResourceId{ 公共字符串get(); } 我们的资源/模型的当前方法: 接口资源{ I id(); } 类用户实现资源{ 公共用户id(); } 我正在努力为我们的DAO类找到一个有效的解决方案。以下是我尝试过但失败的一些方法: =
接口资源ID{
T get();
}
类UserId实现了ResourceId{
公共字符串get();
}
我们的资源/模型的当前方法:
接口资源{
I id();
}
类用户实现资源{
公共用户id();
}
我正在努力为我们的DAO类找到一个有效的解决方案。以下是我尝试过但失败的一些方法: ==选项1==
失败原因:
错误:>预期的
Java中似乎禁止使用多个级别的泛型类型
接口Dao{
R findById(I id);
无效保存(RU);
}
类UserDao实现Dao{
公共用户findById(UserId);
公共作废保存(用户u);
}
==选项2==失败原因:
UserDao不是抽象的,并且不会覆盖Dao中的抽象方法save(R)
而且刀看起来很笨。UserDao应该是一个Dao对象
接口Dao{
R findById(I id);
无效保存(RU);
}
类UserDao实现Dao{
公共用户findById(UserId);
公共作废保存(用户u);
}
==选项3==失败原因:
UserDao不是抽象的,并且不会覆盖Dao中findById(I)的抽象方法
即使有效,我也不受R实际实现的ResourceId的约束
接口Dao{
R findById(I id);
无效保存(RU);
}
类UserDao实现Dao{
公共用户findById(UserId);
公共作废保存(用户u);
}
==选项4==编译。
然而,UserDao中的findById必须采用ResourceId类型的泛型参数,而不是UserId。此外,在#findById的实现中,我们必须将#get()的结果转换为字符串。
通常问题是ResourceId的类型不受R实际实现的ResourceId的约束
接口Dao{
R findById(资源id);
无效保存(RU);
}
类UserDao实现Dao{
公共用户findById(ResourceId);
公共作废保存(用户u);
}
==选项5==编译。
然而刀看起来很愚蠢。我们想要使用的ResourceId(即UserId)的信息已经在资源(即User)的实现中可用。没有更干净的方法吗
接口Dao{
R findById(I id);
无效保存(RU);
}
类UserDao实现Dao{
公共用户findById(UserId);
公共作废保存(用户u);
}
有什么办法可以解决这个问题吗?你的选项#1可以通过适当调整来解决。首先将ResourceId
通用类型规范添加到Dao
声明中:
static interface Dao<I extends ResourceId<?>, R extends Resource<I>> {
R findById(I id);
void save(R u);
}
由于您不需要知道ResourceId
(
)在资源
类的上下文中的泛型类型是什么,因此您可以使用通配符将其忽略:
static interface Resource<I extends ResourceId<?>> {
I id();
}
静态接口资源>{
I id();
}
静态类用户实现资源{
公共用户id(){return null;}
}
静态接口Dao接口资源{
是一个原始类型。您需要另一个类型变量,例如接口资源{
@AndyTurner:谢谢你的评论!好吧,我想我明白了。Java不能暗示接口中使用的泛型类型。因此对于资源/模型,我必须将接口创建为Resource
,并且一个适当的实现User implements Resource
。对于DAO类,我必须在接口为Dao
,一个合适的实现UserDao实现了Dao
。好吧,我想我明白了,但我仍然对Java感到失望,因为没有更干净的方法。嘿,Marco,是的,这肯定会有帮助。感谢您花时间给出详细的答案!是的,我认为这样做是必要的(见选项5),我只是希望有一种更干净的方法。我的意思是,现在在我们的代码中,当我需要一个UserDao时,我会传递一个Dao
,它看起来有点冗长。特别是考虑到我认为Java可能暗示“UserId”类型来自用户。当然没什么大不了的,只是希望有一个更干净的方法。再次感谢您的澄清!:)
static interface Resource<I extends ResourceId<?>> {
I id();
}
public class NestedGenerics {
static interface ResourceId<T> {
T get();
}
static class UserId implements ResourceId<String> {
public String get() { return null; }
}
static interface Resource<I extends ResourceId<?>> {
I id();
}
static class User implements Resource<UserId> {
public UserId id() { return null; }
}
static interface Dao<I extends ResourceId<?>, R extends Resource<I>> {
R findById(I id);
void save(R u);
}
static class UserDao implements Dao<UserId, User> {
public User findById(UserId id) { return null; }
public void save(User u) {}
}
}