gpt4 book ai didi

Java 8 方法引用和重写方法

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:22:16 26 4
gpt4 key购买 nike

我在 Java 8 中使用 lambda 和方法引用已有一段时间了,有一件事我不明白。这是示例代码:

    Set<Integer> first = Collections.singleton(1);
Set<Integer> second = Collections.singleton(2);
Set<Integer> third = Collections.singleton(3);

Stream.of(first, second, third)
.flatMap(Collection::stream)
.map(String::valueOf)
.forEach(System.out::println);

Stream.of(first, second, third)
.flatMap(Set::stream)
.map(String::valueOf)
.forEach(System.out::println);

两个流管道做同样的事情,它们打印出三个数字,每行一个。不同的是他们的第二行,似乎只要有方法就可以简单地替换继承层次中的类名(Collection接口(interface)有默认方法“stream”,在Set接口(interface)中没有重新定义)。我尝试了如果使用这些类一次又一次地重新定义该方法会发生什么:

private static class CustomHashSet<E> extends HashSet<E> {
@Override
public Stream<E> stream() {
System.out.println("Changed method!");
return StreamSupport.stream(spliterator(), false);
}
}

private static class CustomCustomHashSet<E> extends CustomHashSet<E> {
@Override
public Stream<E> stream() {
System.out.println("Changed method again!");
return StreamSupport.stream(spliterator(), false);
}
}

在更改第一个、第二个和第三个分配以使用这些类后,我可以替换方法引用 (CustomCustomHashSet::stream),毫不奇怪,即使我使用 Collection::stream,它们也会在所有情况下打印出调试消息.看来您不能使用方法引用来调用超重写方法。

有运行时差异吗?什么是更好的做法,引用顶级接口(interface)/类或使用具体的已知类型(Set)?谢谢!

编辑:澄清一下,我知道继承和 LSP,我的困惑与 Java 8 中方法引用的设计有关。我的第一个想法是更改方法引用中的类会改变行为,它会调用 super来自所选类的方法,但正如测试所示,它没有区别。更改创建的实例类型确实会改变行为。

最佳答案

即使是方法引用也必须遵守方法覆盖的 OOP 原则。否则,代码如下

public static List<String> stringify(List<?> o) {
return o.stream().map(Object::toString).collect(Collectors.toList());
}

不会按预期工作。

关于方法引用使用哪个类名:我更喜欢使用声明方法的最通用的类​​或接口(interface)。

原因是这样的:你写你的方法来处理Set的集合。稍后您会发现您的方法也可能对 Collection 的集合有用,因此您相应地更改了您的方法签名。现在,如果方法中的代码始终引用 Set 方法,则您也必须调整这些方法引用:

来自

public static <T> void test(Collection<Set<T>> data) {
data.stream().flatMap(Set::stream).forEach(e -> System.out.println(e));
}

public static <T> void test(Collection<Collection<T>> data) {
data.stream().flatMap(Collection::stream).forEach(e -> System.out.println(e));
}

你也需要改变方法体,而如果你把你的方法写成

public static <T> void test(Collection<Set<T>> data) {
data.stream().flatMap(Collection::stream).forEach(e -> System.out.println(e));
}

您不必更改方法体。

关于Java 8 方法引用和重写方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39545942/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com