无法使用有界通配符传递通用子 class 的内部 class
Unable to pass inner class of a generic subclass using bounded wildcard
免责声明:该问题包含使用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()
方法,该方法 return 是一个泛型类型的对象:
public interface Func0<T> { T call(); }
数据源声明为:
private final Observable<AndroidApiMetricDataSource> androidApiMetricDataSource;
private final Observable<CacheMetricDataSource> cacheMetricDataSource;
那么,为什么会失败? defer
期待一个 Observable<T>
而我给它一个 Observable<? extends MetricDataSource>
,它应该很适合 T
.
编辑:如果我用当前class中的私有方法替换defer
方法,然后将Observable<T>
替换为T
在参数和 return 类型中,它编译。但是,我不得不使用原来的Observable
方法。
所以,这种方式失败了:
private static <T> Observable<T> defer(Func0<Observable<T>> observableFactory) {
return null;
}
它编译的这个:
private static <T> T defer(Func0<T> observableFactory) {
return null;
}
你能试试这个吗?
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,它会认为它引用了可能独立更改的不同类型,因此不相等。但不确定
好吧,如果我将数据源的声明从
更改为
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>
。
(将 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>
。这显然是安全的,这样做没有罪恶感。
免责声明:该问题包含使用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()
方法,该方法 return 是一个泛型类型的对象:
public interface Func0<T> { T call(); }
数据源声明为:
private final Observable<AndroidApiMetricDataSource> androidApiMetricDataSource;
private final Observable<CacheMetricDataSource> cacheMetricDataSource;
那么,为什么会失败? defer
期待一个 Observable<T>
而我给它一个 Observable<? extends MetricDataSource>
,它应该很适合 T
.
编辑:如果我用当前class中的私有方法替换defer
方法,然后将Observable<T>
替换为T
在参数和 return 类型中,它编译。但是,我不得不使用原来的Observable
方法。
所以,这种方式失败了:
private static <T> Observable<T> defer(Func0<Observable<T>> observableFactory) {
return null;
}
它编译的这个:
private static <T> T defer(Func0<T> observableFactory) {
return null;
}
你能试试这个吗?
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,它会认为它引用了可能独立更改的不同类型,因此不相等。但不确定
好吧,如果我将数据源的声明从
更改为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>
。
(将 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>
。这显然是安全的,这样做没有罪恶感。