使用方法返回的收集器时通用类型不匹配 - Java 17
Generic type mismatch while using a Collector returned by the method - Java 17
我正在试验 records
和 streams。
我创建了这些 记录 来计算文本中的字母数。
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()
声明 return 类型如下:
Collector<Letter, Object, LetterCount>
这意味着通过此方法 return 收集器的 可变容器 的类型预计为 Object
.
提醒: 泛型是 不变的 ,也就是说,如果你说 Object
你只需要提供 Object
(不是它的子类型,不是 未知类型 ?
,只有 Object
类型本身)。
由于以下几个原因,这是不正确的:
JDK 中的所有 收集器 built-in 都隐藏了它们的可变容器类型。您在代码中使用的收集器 conting
声明为 return Collector<T,?,Long>
。在引擎盖下,它使用 summingLong
,而 return 又是 Collector<T,?,Long>
,尽管它在内部使用 long[]
作为 容器 .那是因为公开这些实现细节没有意义。因此,您声明的 return 类型的通用参数不符合您正在 returning 的 collector 的通用参数。 IE。因为给定了一个未知类型 ?
,所以你不能向 return 声明一个 Object
.
即使您不使用 built-in 收集器,而是使用您自己的 自定义收集器 ,这仍然不是一个好主意公开其容器的实际类型。只是因为将来某个时候,您可能想要更改它。
Object
class 是不可变的,因此将其用作容器类型是徒劳的(如果您尝试实现自定义收集器) 因为它没有能力积累数据。
底线:collector中的第二个泛型参数return由countingLetters()
方法编辑不正确。
要修复它,您必须将 可变容器 的类型更改为:
- 未知类型
?
,它包含所有可能的类型,即预期提供的收集器可能具有任何类型的可变容器(这就是所有收集器在JDK 已申报);
- 或上界通配符
? extends Object
(这基本上是描述 未知类型 的更详细的方式)。
public static Collector<Letter, ?, LetterCount> countingLetters()
我正在试验 records
和 streams。
我创建了这些 记录 来计算文本中的字母数。
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()
声明 return 类型如下:
Collector<Letter, Object, LetterCount>
这意味着通过此方法 return 收集器的 可变容器 的类型预计为 Object
.
提醒: 泛型是 不变的 ,也就是说,如果你说 Object
你只需要提供 Object
(不是它的子类型,不是 未知类型 ?
,只有 Object
类型本身)。
由于以下几个原因,这是不正确的:
JDK 中的所有 收集器 built-in 都隐藏了它们的可变容器类型。您在代码中使用的收集器
conting
声明为 returnCollector<T,?,Long>
。在引擎盖下,它使用summingLong
,而 return 又是Collector<T,?,Long>
,尽管它在内部使用long[]
作为 容器 .那是因为公开这些实现细节没有意义。因此,您声明的 return 类型的通用参数不符合您正在 returning 的 collector 的通用参数。 IE。因为给定了一个未知类型?
,所以你不能向 return 声明一个Object
.即使您不使用 built-in 收集器,而是使用您自己的 自定义收集器 ,这仍然不是一个好主意公开其容器的实际类型。只是因为将来某个时候,您可能想要更改它。
Object
class 是不可变的,因此将其用作容器类型是徒劳的(如果您尝试实现自定义收集器) 因为它没有能力积累数据。
底线:collector中的第二个泛型参数return由countingLetters()
方法编辑不正确。
要修复它,您必须将 可变容器 的类型更改为:
- 未知类型
?
,它包含所有可能的类型,即预期提供的收集器可能具有任何类型的可变容器(这就是所有收集器在JDK 已申报); - 或上界通配符
? extends Object
(这基本上是描述 未知类型 的更详细的方式)。
public static Collector<Letter, ?, LetterCount> countingLetters()