我有以下代码:
public class Chap20 {
public static void main(String[] args) {
String[] names = { "John", "Jane" };
Stream<String> namesStream = Stream.of(names);
Path path = Paths.get(".");
Stream<Path> files;
try {
files = Files.list(path);
files.forEach(System.out::println);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
现在这里是file.forEach方法签名:
void java.util.stream.Stream.forEach(Consumer<? super Path> action)
我正在读取它作为一种接受类型的消费者的方法,该类型至少是Path类型或Path的超类,但我可能会错过它,因为System.out不是Path的超类。
有人可以解释一下如何正确阅读吗?
答案 0 :(得分:2)
? super Path
说:&#39;它必须是Path的超级类。
System.out.println
接受Object
。 Object
是Path
的超类,因此这是正确的。
答案 1 :(得分:2)
您正在阅读完全正确的IMO,您可能会被Sub test()
Dim rng As Range
Dim rngVals As Variant
Set rng = YourSheet.ListObjects("Table2").Range
rngVals = rng.Value
YourSheet.ListObjects("Table2").Delete
rng.Value = rngVals
Set rng = Nothing
End Sub
符号误导。这不是关于::
是System.out
还是关于暗示参数Path
(例如)你的问题因为方法参考而无法看到(进一步阅读)。
这里有几件事,第一件叫PECS;这就是宣言为x
或? super P_OUT
的原因。基本上这意味着你可以阅读任何超级类型的? super Path
。唯一安全的是Path
(或任何子类型,但你不知道究竟是哪一个)。
为了简单起见,你可以这样编写它,例如:
Object
或者因为编译器可以看到(推断)类型为Stream.of("John", "Jane")
.forEach((Object x) -> System.out.println(x)); // Object
:
String
或者你可以省略该声明,让编译器完成它的工作:
Stream.of("John", "Jane")
.forEach((String x) -> System.out.println(x)); // String
现在第二部分称为Method Reference。
而不是写作:
Stream.of("John", "Jane")
.forEach(/* this is infered as String here */ x -> System.out.println(x));
你可以写得更简单:
Stream.of("John", "Jane")
.forEach(x -> System.out.println(x));
此处隐含 Stream.of("John", "Jane")
.forEach(System.out::println);
参数(类型为x
)。
答案 2 :(得分:1)
方法签名表示forEach的Stream方法接受一个Consumer,它消耗它迭代的Stream中的每个元素,在你的情况下是一个Paths集合。
Consumer指的是functional interface,它接受输入并且不返回任何结果。它是Java 8中实现的many之一,可与Lambdas和method references一起使用。功能接口只包含一个抽象方法,也称为功能方法。
forEach 方法用于迭代集合并对每个元素应用操作。传递的操作或“行为”(实现Consumer接口的任何类)是对集合的每个元素执行的 action 或lambda。
forEach是Iterable接口中的API(也添加了Java 8),“为Iterable的每个元素执行给定的操作,直到所有元素都被处理或该操作会抛出异常“。它与Java for loop 的不同之处在于它是一个内部迭代器,而不是外部迭代器。