2017-08-01 4 views
2

このコードは論理的ですが、コンパイラが間違った型の述語isBondAssetについて不平を言っているのはなぜですか?java 8述語型の不一致、このコードは論理的です。

「資産を拡張する任意のタイプの述語」は、「資産を拡張する任意のタイプのスーパータイプの述語」か、間違っていますか?私は間違っていないですので、もしそれがその主な理由の

Predicate<? super Asset> isBondAsset 

一つでなければなりませんStream#filter

/** 
* Returns a stream consisting of the elements of this stream that match 
* the given predicate. 
* 
* <p>This is an <a href="package-summary.html#StreamOps">intermediate 
* operation</a>. 
* 
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>, 
*     <a href="package-summary.html#Statelessness">stateless</a> 
*     predicate to apply to each element to determine if it 
*     should be included 
* @return the new stream 
*/ 
Stream<T> filter(Predicate<? super T> predicate); 

によると、Predicatesを使用する可能性が既にのために定義されて

private static class Asset 
{ 
    public enum AssetType 
    { 
     BOND, 
     STOCK; 
    } 

    private final AssetType type; 
    private final int value; 

    public Asset (AssetType type, int value) 
    { 
     this.type = type; 
     this.value = value; 
    } 

    public AssetType getType() 
    { 
     return type; 
    } 

    public int getValue() 
    { 
     return value; 
    } 
} 

private static class AssetUtils 
{ 
    public static int totalBondAssetValues (Collection <? extends Asset> assets) 
    { 
     Predicate<? extends Asset> isBondAsset = asset -> Asset.AssetType.BOND.equals(asset.getType()); 

     return assets.stream().filter(isBondAsset).mapToInt(Asset::getValue).sum(); 
    } 
} 
+1

なぜ「述語」を使用しませんか?これは 'Asset'のポリモーフィックで、' Asset'のサブタイプを受け入れます。それはあなたが望むものではありませんか? –

+0

はい私は@ Jean-BaptisteYunèsを知っていますが、私は可能な限り自分のタイプに柔軟性を持たせたい – marsouf

+2

次にhttps://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in- Java –

答えて

2

の2つの型変数に名前を挙げてみましょう:

Collection<T> assets; 
Predicate<R> isBondAsset; 

コンパイラはTR両方がAssetのサブタイプがあることを知っているが、それはそれは上に行くために持っているすべてです。 Predicate<R>Collection<T>の場合Rは、Tのスーパータイプである必要がありますが、そのように宣言することはできません。

をワイルドカードで宣言する理由はありません。単にそれをPredicate<Asset>にするだけです。コンパイラは、Assetがすべての型のスーパータイプであることをコンパイラが認識しているため、コードはコンパイルされます。? extends Asset

+0

のコンテキストで代用することができます。Rをと同等の型にすると、ストリームのフィルタメソッドは述語である必要があります。私の場合、私はフィルタメソッドに型述語を与えました。述語のコンテキストで有効です marsouf

+1

あなたのストリームは 'extends Asset'によって' T'によってパラメータ化されています。あなたの述語は 'extends Asset'という' R'によってパラメータ化されています。 'TがRを伸ばす '、' T super R'はそうではない。 – Misha

+1

これはよくある混乱の原因です。 '<?extends Asset> 'は同じメソッドで2回表示されますが、コンパイラは同じ型を参照するとは想定しません。 – Misha

2

<T>スーパータイプ:

List<String> stringList = Arrays.asList("1","22","3","44"); 

Predicate<Object> objectPredicate = o -> o.getClass().equals(String.class); 

Predicate<CharSequence> charSequencePredicate = ch -> ch.length() == 2; 

Predicate<String> stringPredicate = s -> s.contains("2"); 

stringList.stream().filter(objectPredicate).forEach(System.out::println); 

stringList.stream().filter(charSequencePredicate).forEach(System.out::println); 

stringList.stream().filter(stringPredicate).forEach(System.out::println); 
+0

ストリームのフィルタメソッドの型が述語の場合、ストリームのフィルタメソッドには、型Predicate <?スーパー? T>を拡張し、型Predicate <? extends Asset>は述語<?スーパー? extends Asset>、原因 marsouf

関連する問題