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

时间:2015-10-30 10:23:07

标签: java generics java-8 cqengine

我使用cqengine进行集合索引:

<VirtualHost *:80>
    ServerAdmin stuart.brown@example.co.uk
    ServerName stuart.com
    DocumentRoot /var/www/stuart.com/public_html
    Alias /stuart.com "/var/www/stuart.com/public_html"
    <Directory "/var/www/stuart.com/public_html">
            Options None
            AllowOverride None
            Order allow,deny
            Allow from all
    </Directory>
</VirtualHost>

此代码未编译,因为:

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

也许,这个问题有其他一些解决方案吗?

1 个答案:

答案 0 :(得分:5)

我认为,创建新类(如包装器)会导致修复通用签名错误的开销很大。我会创建一个像

这样的委托方法
@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中传播并允许这样的返回类型只是在下一个API使用时引发错误。但是,据我所知,Attribute仅生成A但不消费它们,我们可以在此处放宽签名并接受Attribute<…,? extends A>,跟随PECS模式。

使用此帮助程序,您的代码应该顺利编译:

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