关于 Java 的 Supplier<T>接口的疑问,为什么可以传入静态方法

2021-07-23 00:35:19 +08:00
 0576coder

这三段代码其实是一致的

        //生成随机数流
        Stream<Double> randoms = Stream.generate(Math::random);
        
        Stream<Double> randoms2 = Stream.generate(() -> Math.random());
        
        Stream<Double> randoms3 = Stream.generate(new Supplier<Double>() {
            @Override
            public Double get() {
                return Math.random();
            }
        });

后面两段我都能理解,第一段为什么 Math 的静态方法也算是可以当做 Supplier 接口的实现者,我有点想不通

1274 次点击
所在节点    Java
7 条回复
passerbytiny
2021-07-23 00:46:10 +08:00
第一,Math::random 是 () -> Math.random() 的等价简写。

第二,Math::random 是 lambda 表达式,不是静态方法。
0576coder
2021-07-23 00:56:36 +08:00
@passerbytiny

对不起 丢人了 我最近 php 也写 java 也写 暴露智商了 半夜脑子转不过来来- -
zhady009
2021-07-23 09:47:43 +08:00
因为 Supplier 是没有入参有返回值的方法, Math.random 也是一样 所以可以用静态方法引用
其他的还有构造器和实例方法
ztcaoll222
2021-07-23 10:54:08 +08:00
第一个就是个语法糖,等价于第二个
unco020511
2021-07-23 11:20:06 +08:00
第一个和第二个你都可以理解为是语法糖,第三个是原始写法
mijazz
2021-07-23 14:24:55 +08:00
上面讲的都蛮清晰暴力了,我来凑个热闹。[functional interface]( https://mijazz.icu/posts/Functional-Interface-and-its-Underlying-Pattern/#:~:text=Supplier%3CT%3E,LocalDate%3A%3Anow)
第一个写法是用 double colon(`::`)表示的 Method Declaration,它既可以作用在静态方法也能作用在实例方法上,且用`::new`也能作为 Constructor 的 Method Declaration 。
至于`Supplier`,只是`java.util.function`下面的众多函数式接口的一类,只要符合不接参数但又返回一个参数的方法,都能被 method declaration 看作是 supplier 类型的函数式接口。
且鉴于第三种写法我感觉我像在 Effective Java 里看过,不建议,因为你的返回类是基本类型是 int,double,long 里的一种,在上述包内有提供上述三个原始类作为返回值的特殊 functional interface,在这个情况下是 DoubleSupplier,你就不用使用包装类来增加多一轮装箱拆箱了。
题外话,为什么不用`ThreadLocalRandom`的`DoubleStream`呢 :-)
有错的请加以指正。
ikas
2021-07-25 11:00:22 +08:00
第一种是方法引用,第二种 lambda 表达式
另外第一种与第二种不完全等价,他们具体的实现,是根据不同情况有区别的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/791189

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX