考虑以下课程
public interface SortBy<S> {
}
public class CommentSortBy<S> implements SortBy<S> {
public static CommentSortBy<Date> CREATION = new CommentSortBy<Date>();
public static CommentSortBy<Integer> VOTES = new CommentSortBy<Integer>();
}
public class SomeQueryUnsafe {
public <M, S extends SortBy<M>> void setSort(S sortBy, M min) {
//Set relevant values
}
}
目前用作:
public SomeQueryUnsafe createCommentQueryUnsafe() {
return new SomeQueryUnsafe();
}
public void test() {
createCommentQueryUnsafe().setSort(CommentSortBy.CREATION, new Date());
}
虽然这有效,但问题是createCommentQueryUnsafe()
未指定sortBy
的限制。用户可以自由地传递UserSortBy.NAME
,即使在这种情况下没有意义
我无法弄清楚如何写这个,因为只是将<B extends SortBy>
添加到类签名意味着我失去了限制方法中min
参数的能力。我不能使用<M, S extends B & SortBy<M>>
之类的内容作为its a compiler error。使用通配符魔法的其他尝试只会导致更高的复杂性和编译器错误。将排序移动到createCommentQuery()
方法意味着每个查询都需要2个方法,这是一个疯狂的重复代码量
我如何编写泛型,以便createCommentQuery()
将sortBy
参数限制为CommentSortBy
,同时仍然将min
限制在SortBy类中的S参数?< / p>
答案 0 :(得分:3)
出于你所指出的原因,这确实是一个棘手的问题。我尝试了各种方法,但它们都被generics limitation you cited击败了。最终,如果您想要指定的类型安全,您似乎需要进行一些设计更改。
对于通用类型限制使用SortBy
实现的继承层次结构似乎特别导致了这种僵局。我尝试将该限制解耦为SortBy
上的新类型参数,该参数代表查询对象本身,例如Comment
,User
等。这是我提出的设计:
static class Comment { }
static class User { }
interface SortBy<T, M> { }
static class CommentSortBy<M> implements SortBy<Comment, M> {
static final CommentSortBy<Date> CREATION = new CommentSortBy<Date>();
static final CommentSortBy<Integer> VOTES = new CommentSortBy<Integer>();
}
static class UserSortBy<M> implements SortBy<User, M> {
static final UserSortBy<String> NAME = new UserSortBy<String>();
}
static class Query<T> {
public <M> void setSort(SortBy<T, M> sortBy, M min) {
//Set relevant values
}
}
public static void main(String[] args) {
new Query<Comment>().setSort(CommentSortBy.CREATION, new Date());
new Query<Comment>().setSort(UserSortBy.NAME, "Joe"); //compiler error
}
(ideone)