我有这段代码,但它给了我一个错误:
类型不匹配:无法从int转换为Character
Stream.iterate('a', i -> i + 1).limit(26).forEach(System.out::println);
尽管可以写int i = 'a';
我知道我可以这样写,但是对于一个简单的任务来说似乎太多了。
Stream.iterate('a', i -> (char)(i + 1)).limit(26).forEach(System.out::println);
为什么Java类型推断失败?
答案 0 :(得分:28)
i -> i + 1
无法编译的原因是,您正试图将int
隐式地转换为Character
,编译器无法单独完成此工作
换句话说,您可以将Stream.iterate('a', i -> i + 1)
视为:
Stream.iterate('a', (Character i) -> {
int i1 = i + 1;
return i1; // not possible
});
您已经注意到,明确强制转换为char
可以解决此问题:
Stream.iterate('a', i -> (char)(i + 1))...
更好的做法是:
IntStream.rangeClosed('a', 'z').forEach(c -> System.out.println((char)c));
这更好,因为:
h
来说字母iterate
,则除了要输入h
作为{{1 }},因为您需要找到数字以截断无限流。rangeClosed
一起生成 infinite 流,在此特定情况下,该流比具有iterate
的 finite 开销更大。此外,并行运行rangeClosed
要容易得多,并不是您想在这种特定情况下运行,而是要牢记。这是Brian Goetz在Generators as sources上的一些讨论。等...
答案 1 :(得分:17)
怎么样:
Stream.iterate('a', i -> ++i).limit(26).forEach(System.out::println);
i -> i + 1
不起作用,因为i
是Character
,并且i + 1
导致隐式变窄转换(JLS 5.1.3),这是不允许的。您可以如图所示明确地投射它。但是++i
之所以有效,是因为(来自JLS 15.15.1):
在加法之前,对值1和变量的值执行二进制数值提升(第5.6.2节)。如有必要,可通过缩小原始转换(第5.1.3节)来对和进行缩小,和/或在存储变量之前将其进行装箱转换(第5.1.7节)至变量的类型。
++
运算符负责缩小转换,而无需我们显式转换