第三方库中的通用方法限制规避

Generic method restriction circumvention in a 3rd party library

我使用 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<ChronoLocalDate>ChronoLocalDate,这意味着有必要在泛型方法声明中使用通配符边界。我想,在这种情况下,创建实现 Comparable<>LocalDate 包装器是一种解决方法。

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

我认为,创建新的 类,就像一个包装器一样,对于修复一般签名错误来说开销很大。我会创建一个像

这样的委托方法
@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<A> 上,它应该是 A extends Comparable<? super A>,但是在这里修复它无济于事,因为这种模式遍布 API 并允许这样的 return 类型只会在下一次 API 使用时引发错误。但是,据我所知,Attribute 只产生 A 而不会消耗它们,因此我们可以在此处放宽签名并在 [=17= 之后接受 Attribute<…,? extends A> ] 模式。

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

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