如何创建使用另一个通用Java接口键入的通用Java接口?

如何创建使用另一个通用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类找到一个有效的解决方案。以下是我尝试过但失败的一些方法: =

我们方法的目标是向现有的DAO和模型类引入接口。模型类由各种类型的资源ID标识,资源ID不仅仅是随机数,还包含语义和行为。因此,我们必须用对象而不是基元类型来表示资源ID

资源ID的当前方法:

接口资源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) {}
    }
}