首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Predicate<?超级X>.and(Predicate<?)超级X>)不适用于论点Predicate<?超级X>

Predicate<?超级X>.and(Predicate<?)超级X>)不适用于论点Predicate<?超级X>
EN

Stack Overflow用户
提问于 2019-08-25 20:42:03
回答 2查看 653关注 0票数 0

我必须对实现Predicate<MoneyOperation>的业务对象执行Predicate<MoneyOperation>

出现问题的代码是使用and()调用的行:

代码语言:javascript
复制
        Predicate<? super MoneyOperation> predicate =
           new MoneyOperationDateWithRadioButtonsPredicate(newv, 
                  thisDayRdBtn.getValue(), date);

        filteredData.setPredicate(filteredData.getPredicate().and(predicate));

错误:

代码语言:javascript
复制
The method and(Predicate<? super capture#14-of ? super MoneyOperation>) 
in the type Predicate<capture#14-of ? super MoneyOperation> is not applicable 
for the arguments (Predicate<capture#15-of ? super MoneyOperation>)

尽管在没有调用的情况下将predicate传递给setPredicate()时,and()编译器不会引发任何错误。

MoneyOperationDateWithRadioButtonsPredicate类:

代码语言:javascript
复制
public class MoneyOperationDateWithRadioButtonsPredicate extends MoneyOperationFieldPredicate<LocalDate> { ... }

MoneyOperationFieldPredicate类:

代码语言:javascript
复制
public abstract class MoneyOperationFieldPredicate<T> implements Predicate<MoneyOperation> { ... }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-08-25 20:53:02

这只是类型系统的一个限制,因为Java没有使用Predicate没有生产者方法(在PECS意义上)来不同地处理类型这一事实。

考虑两个List<? super Integer>实例:您不能在这里执行list1.addAll(list2),原因与不能在这里执行predicate1.and(predicate2)相同:这是为了防止list1可能是一个List<Integer>,而list2是一个List<Object>:您不应该将对象添加到只包含整数的列表中。

这对List来说是一个实际的问题,因为List有生产者方法(例如List.get(int)),即为您提供特定类型的实例的方法。Predicate只有使用者方法(确切地说,是Predicate.test<T>),因此不存在Predicate会给出意外类型的对象的情况。

但是,编译器不考虑类是否没有生产者方法(或者没有使用者方法):它假设两个方法都存在(实际上,它们可能存在于子类中),因此它阻止了您这样做。也许很烦人,但事情就是这样。

最简单的方法是构造一个lambda来显式测试这两个谓词:

代码语言:javascript
复制
setPredicate(a -> predicate1.test(a) && predicate2.test(b))

你也许可以用这个诡计:

代码语言:javascript
复制
setPredicate(Stream.of(predicate1, predicate2).map(a -> a).reduce(Predicate::and))

但是,无论是通过规范,还是通过奇怪的实现,我都不太满意。

票数 3
EN

Stack Overflow用户

发布于 2019-08-25 21:00:21

这里的问题是捕获。让我们看看这些约束意味着什么:

Predicate<? super MoneyOperation>是一个谓词,可以接受MoneyOperation,也可能是超类,并返回布尔值。这意味着它可以是一个接受Predicate<Object>并返回布尔值的Object

现在有一个潜在的问题:

让我们假设MoneyOperation扩展了GenericOperation并实现了SomeInterface

实际上,第一个Predicate<? super MoneyOperation>可能是Predicate<GenericOperation>,第二个Predicate<? super MoneyOperation>Predicate<SomeInterface>。( Java编译器无法分辨)将MoneyOperation传递给两者都很好,但是将它们组合在一起将需要将其类型限制为Predicate<MoneyOperation>。虽然这对于Predicate来说是可以的,但对于其他情况则可能不适用。

这就是为什么Java不允许这样做。

如果你知道Predicate<MoneyOperation>是一个,就使用它。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57649578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档