V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
0576coder
V2EX  ›  Java

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

  •  
  •   0576coder · 2021-07-23 00:35:19 +08:00 · 1169 次点击
    这是一个创建于 979 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这三段代码其实是一致的

            //生成随机数流
            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 接口的实现者,我有点想不通

    7 条回复    2021-07-25 11:00:22 +08:00
    passerbytiny
        1
    passerbytiny  
       2021-07-23 00:46:10 +08:00 via Android
    第一,Math::random 是 () -> Math.random() 的等价简写。

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

    对不起 丢人了 我最近 php 也写 java 也写 暴露智商了 半夜脑子转不过来来- -
    zhady009
        3
    zhady009  
       2021-07-23 09:47:43 +08:00
    因为 Supplier 是没有入参有返回值的方法, Math.random 也是一样 所以可以用静态方法引用
    其他的还有构造器和实例方法
    ztcaoll222
        4
    ztcaoll222  
       2021-07-23 10:54:08 +08:00
    第一个就是个语法糖,等价于第二个
    unco020511
        5
    unco020511  
       2021-07-23 11:20:06 +08:00
    第一个和第二个你都可以理解为是语法糖,第三个是原始写法
    mijazz
        6
    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
        7
    ikas  
       2021-07-25 11:00:22 +08:00
    第一种是方法引用,第二种 lambda 表达式
    另外第一种与第二种不完全等价,他们具体的实现,是根据不同情况有区别的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3118 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:29 · PVG 22:29 · LAX 07:29 · JFK 10:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.