免责声明:此问题包含使用rxjava
库的代码,但问题与此无关。我提供了所有必要的信息,以允许不熟悉该库的人回答。
我有以下方法根据是否缓存某些数据来选择数据源:
public Observable<? extends MetricDataSource> createForOwners() {
return Observable.defer(new Func0<Observable<? extends MetricDataSource>>() {
@Override
public Observable<? extends MetricDataSource> call() {
if (ownersCache.isCached()) {
return cacheMetricDataSource;
} else {
return androidApiMetricDataSource;
}
}
});
}
无法使用以下错误进行编译:
Error:(29, 26) error: method defer in class Observable<T#2> cannot be applied to given types;
required: Func0<Observable<T#1>>
found: <anonymous Func0<Observable<? extends MetricDataSource>>>
reason: cannot infer type-variable(s) T#1
(argument mismatch; <anonymous Func0<Observable<? extends MetricDataSource>>> cannot be converted to Func0<Observable<T#1>>)
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>defer(Func0<Observable<T#1>>)
T#2 extends Object declared in class Observable
Observable.defer
的签名是:
public final static <T> Observable<T> defer(Func0<Observable<T>> observableFactory)
Func0
基本上包含一个返回泛型类型对象的call()
方法:
public interface Func0<T> { T call(); }
数据源声明为:
private final Observable<AndroidApiMetricDataSource> androidApiMetricDataSource;
private final Observable<CacheMetricDataSource> cacheMetricDataSource;
那么,为什么会失败? defer
期待Observable<T>
并且我正在给它Observable<? extends MetricDataSource>
,这应该与T
完全吻合。
编辑:如果我将defer
方法替换为当前类中的私有方法,然后在参数和返回中将Observable<T>
替换为T
类型,它编译。但是,我必须使用原始的Observable
方法。
所以,这样就失败了:
private static <T> Observable<T> defer(Func0<Observable<T>> observableFactory) {
return null;
}
它编译的这个:
private static <T> T defer(Func0<T> observableFactory) {
return null;
}
答案 0 :(得分:2)
你能尝试一下吗?
public <T extends MetricDataSource> Observable<T> createForOwners() {
return Observable.defer(new Func0<Observable<T>>() {
@Override
public Observable<T> call() {
if (ownersCache.isCached()) {
return cacheMetricDataSource;
} else {
return androidApiMetricDataSource;
}
}
});
}
我不确定,但我猜它是因为如果你没有将它绑定到T,它会认为它引用了可能独立改变的不同类型,因此不相等。但不确定
答案 1 :(得分:1)
好吧,如果我从
更改数据源的声明,看起来就好了private final Observable<AndroidApiMetricDataSource> androidApiMetricDataSource;
private final Observable<CacheMetricDataSource> cacheMetricDataSource;
到
private final Observable<MetricDataSource> androidApiMetricDataSource;
private final Observable<MetricDataSource> cacheMetricDataSource;
然后我可以声明方法
public Observable<MetricDataSource> createForOwners() {
return Observable.defer(new Func0<Observable<MetricDataSource>>() {
@Override
public Observable<MetricDataSource> call() {
if (ownersCache.isCached()) {
return cacheMetricDataSource;
} else {
return androidApiMetricDataSource;
}
}
});
}
现在它编译,一如既往地返回Observable<MetricDataSource>
。
答案 2 :(得分:1)
(将Func0
视为Supplier
,将Observable
视为Iterable
,如果这使问题更加熟悉的话)
这里,Func0和Observable直观协变;在Java中,它们几乎总是与通配符一起使用,否则迟早会出现问题。
defter
的签名当然可以归咎于
<T> Observable<T> defer(Func0<Observable<T>> observableFactory)
它可能更为通用,如
<T> Observable<? extends T> defer(Func0<? extends Observable<? extends T>> observableFactory)
但这也导致了通配地狱......我看不到通配符尖叫声的类型。
我们可以改为,危险地生活,只是省略通配符 - 当问题出现时,做一些演员来解决它。在您的情况下,我们需要将Observable<Subtype>
投射到Observable<Supertype>
。这显然是安全的,并且没有任何负罪感。