簡體   English   中英

使用方法返回的收集器時通用類型不匹配 - Java 17

[英]Generic type mismatch while using a Collector returned by the method - Java 17

我正在試驗recordsstreams

我創建了這些記錄來計算文本中的字母數。

record Letter(int code) {
    Letter(int code) {
        this.code = Character.toLowerCase(code);
    }
}

record LetterCount(long count) implements Comparable<LetterCount> {
    @Override
    public int compareTo(LetterCount other) {
        return Long.compare(this.count, other.count);
    }

    static Collector<Letter, Object, LetterCount> countingLetters() {
        return Collectors.collectingAndThen(
            Collectors.<Letter>counting(), 
            LetterCount::new);
    }
}

這是使用它們的片段:

final var countedChars = text.chars()
    .mapToObj(Letter::new)
    .collect(
        groupingBy(Function.identity(), 
            LetterCount.countingLetters()                      // compilation error
            // collectingAndThen(counting(), LetterCount::new) // this line doesn't produce error
        ));

如果我注釋掉collectingAndThen()用作groupingBy()中的下游收集器,上面顯示的代碼片段不會產生錯誤。

但是,當我嘗試使用LetterCount.countingLetters()作為下游收集器時,編譯器會丟失。

我收到以下錯誤消息:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
        Collector cannot be resolved to a type
        Type mismatch: cannot convert from Collector<Letter,capture#17-of ?,LetterCount> to Collector<Letter,Object,LetterCount>
        The method countingLetters() from the type LetterCount refers to the missing type Collector
        The method entrySet() is undefined for the type Object

接口Collector具有以下聲明:

public interface Collector<T,​A,​R>

其中第二個泛型類型參數A表示可變容器的類型,該容器在內部用於累積歸約結果。 這種類型通常被實現隱藏。

您的方法countingLetters()聲明返回類型如下:

Collector<Letter, Object, LetterCount>

這意味着此方法返回的收集器的可變容器類型應為Object

提醒: generics 是不變的,即如果你說Object你必須只提供Object (不是它的子類型,不是未知類型? ,只有Object類型本身)。

由於以下幾個原因,這是不正確的:

  • JDK 中內置的所有收集器都隱藏了它們的可變容器類型。 您在代碼中使用的收集器條件聲明返回conting Collector<T,?,Long> 在引擎蓋下,它使用summingLong ,它反過來返回Collector<T,?,Long>盡管它在內部使用long[]作為container 那是因為公開這些實現細節沒有意義。 因此,您聲明的返回類型的通用參數不符合您要返回的收集器的通用參數。 即因為你被賦予了未知類型? ,您不能聲明返回Object

  • 即使您不使用內置收集器,而是使用您自己的自定義收集器,公開其容器實際類型仍然不是一個好主意。 僅僅是因為在未來的某個時候,您可能想要更改它。

  • Object class 是不可變的,因此將其用作容器類型(如果您嘗試實現自定義收集器)是徒勞的,因為它無法累積數據。


底線: countingLetters()方法返回的收集器中的第二個通用參數不正確。

要修復它,您必須將可變容器的類型更改為:

  • 未知類型? 它包含所有可能的類型,即預期提供的收集器可能具有任何類型的可變容器(這就是 JDK 中所有收集器的聲明方式);
  • 或上界通配符? extends Object ? extends Object (這基本上是描述未知類型的更詳細的方式)。
public static Collector<Letter, ?, LetterCount> countingLetters()

暫無
暫無

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

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