簡體   English   中英

涉及布爾值的Java 8類型推斷

[英]Java 8 type inference involving Booleans

考慮以下代碼:

class Predicate {
    public boolean eval(EvaluationContext ec) { /* logic here */ }
}

// later ...
List<Predicate> preds = new List<>( /* some predicates here */ );

// now let's use Stream<> to implement the AND logical connective:
// VERSION A:
Boolean resultA = preds.stream()
                       .map(p -> p.eval(context))
                       .reduce(Boolean.TRUE, (a,b) -> Boolean.logicalAnd(a,b));
// Oops: the code above doesn't compile ...   
// Error: incompatible types: java.lang.Object cannot be converted to boolean

// VERSION B:   (add an intermediate variable with explicit type)
Stream<Boolean> v = _children.stream().map(p -> p.eval(context));
Boolean resultB = v.reduce(Boolean.TRUE, (a,b) -> Boolean.logicalAnd(a, b) );
// compiles just fine...

所以,我的問題是:

版本A的結構有什么問題,導致Java編譯器無法正確推斷map()結果的類型? 這是Java中類型推斷算法的限制嗎? 如果是這樣,是否有更好的方法編寫此代碼,以便類型推斷成功?

您的代碼可以使用jdk1.8.0_05jdk1.8.0_20jdk1.8.0_25jdk1.8.0_40 (beta)正常編譯,並且沒有理由假定存在另一個版本存在問題。 當您修正編造代碼的其他錯誤或將您提供給編譯器的實際代碼發布時,它可能會有所幫助。

例如,如果List引用java.util.List並且示例代碼不包含context聲明,則您不能說new List<> 如果找不到context ,則編譯器確實會產生“不兼容類型”的后續錯誤,一旦您修復了其他錯誤,該錯誤就會消失。 令人驚訝的是,第二個示例使用_children而不是preds因此它源自不同的上下文,在該上下文中,很可能不存在此類編譯器錯誤。

順便說一句,您的lambda表達式(a,b) -> Boolean.logicalAnd(a,b)有點奇怪。 使用表達式,例如(a,b) -> a && b或類似Boolean::logicalAnd的方法引用。

但是無論哪種方式,都不建議使用減少。 通過使用短路方法,例如_children.stream().allMatch(p -> p.eval(context)) logical and_children.stream().anyMatch(p -> p.eval(context)) _children.stream().allMatch(p -> p.eval(context)) ,可以獲得更好的性能_children.stream().anyMatch(p -> p.eval(context))表示logical or

有什么原因使您不能僅僅將所有謂詞和在一起使用

Predicate<EvaluationContext> finalTest = preds.stream()
                                              .reduce(((p)->true), Predicate::and);

這樣便有了一個謂詞,並且只編譯一次便可以保存並重用它來測試任意數量的上下文。

重新閱讀后,我注意到您的Predicate類不是java.util.function.Predicate。 為了執行我所描述的,您需要稍微更改您的Predicate類以使其實現Predicate接口:

public class Predicate implements java.util.function.Predicate<EvaluationContext>{
    public boolean eval(EvaluationContext ec) { /* logic here */ }

    @Override
    public boolean test(EvaluationContext t) {
        return eval(t);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM