【问题标题】:Generic method restriction circumvention in a 3rd party library3rd 方库中的通用方法限制规避
【发布时间】:2015-10-30 10:23:07
【问题描述】:

我使用cqengine 进行集合索引:

Attribute<UtilizationEntry, LocalDate> startDateAttr = new SimpleAttribute<UtilizationEntry, LocalDate>() {
    @Override
    public LocalDate getValue(UtilizationEntry object, QueryOptions queryOptions) {
        return object.getStartDate();
    }
};
IndexedCollection<UtilizationEntry> entries = new ConcurrentIndexedCollection<>();
entries.addIndex(NavigableIndex.onAttribute(startDateAttr)); // compilation error in this line

此代码未编译,因为:

Error:(61, 70) java: no suitable method found for onAttribute(com.googlecode.cqengine.attribute.Attribute<entities.UtilizationEntry,java.time.LocalDate>)
method com.googlecode.cqengine.index.navigable.NavigableIndex.<A,O>onAttribute(com.googlecode.cqengine.attribute.Attribute<O,A>) is not applicable
  (inferred type does not conform to equality constraint(s)
    inferred: java.time.chrono.ChronoLocalDate
    equality constraints(s): java.time.chrono.ChronoLocalDate,java.time.LocalDate)
method com.googlecode.cqengine.index.navigable.NavigableIndex.<A,O>onAttribute(com.googlecode.cqengine.index.support.Factory<java.util.concurrent.ConcurrentNavigableMap<A,com.googlecode.cqengine.resultset.stored.StoredResultSet<O>>>,com.googlecode.cqengine.index.support.Factory<com.googlecode.cqengine.resultset.stored.StoredResultSet<O>>,com.googlecode.cqengine.attribute.Attribute<O,A>) is not applicable
  (cannot infer type-variable(s) A,O
    (actual and formal argument lists differ in length))

可能是缺少库设计:LocalDate 实现了扩展Comparable&lt;ChronoLocalDate&gt; 的ChronoLocalDate,这意味着在泛型方法声明中必须使用通配符边界。我想,在这种情况下,创建实现Comparable&lt;&gt; 的LocalDate 包装器是一种解决方法。

或许,这个问题还有其他解决方案?

【问题讨论】:

    标签: java generics java-8 cqengine


    【解决方案1】:

    我认为,创建新类(如包装器)对于修复通用签名错误来说开销很大。我会创建一个委托方法,例如

    @SuppressWarnings("unchecked")
    static <A extends Comparable<A>,O>
                   NavigableIndex<A,O> onAttribute(Attribute<O,? extends A> attribute) {
        return NavigableIndex.onAttribute((Attribute)attribute);
    }
    

    实际上,问题在于声明 A extends Comparable&lt;A&gt; 应该是 A extends Comparable&lt;? super A&gt;,但是在这里修复它并没有帮助,因为这种模式遍布整个 API,并且在这里允许这样的返回类型只会引发错误下一个 API 用法。但是,据我所知,Attribute 只产生 As 而不会消耗它们,所以我们可以在这里放宽签名并接受 Attribute&lt;…,? extends A&gt;,遵循 PECS 模式。

    有了这个助手,你的代码应该可以顺利编译:

    IndexedCollection<UtilizationEntry> entries = new ConcurrentIndexedCollection<>();
    entries.addIndex(onAttribute(startDateAttr));
    

    【讨论】:

    • 感谢关于抑制编译器类型限制的提醒——它为我节省了很多内存。
    • 不错的答案。我是 CQEngine 的作者,我创建了issue 45 看看我将来是否可以根据这个答案改进 API。
    • 我也遇到了这个问题,对于引用 Comparable 的大于/小于查询也需要有一个解决方案。
    猜你喜欢
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    相关资源
    最近更新 更多