V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
0576coder
V2EX  ›  Java

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

  •  
  •   0576coder · Jul 23, 2021 · 1755 views
    This topic created in 1746 days ago, the information mentioned may be changed or developed.

    这三段代码其实是一致的

            //生成随机数流
            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 replies    2021-07-25 11:00:22 +08:00
    passerbytiny
        1
    passerbytiny  
       Jul 23, 2021 via Android
    第一,Math::random 是 () -> Math.random() 的等价简写。

    第二,Math::random 是 lambda 表达式,不是静态方法。
    0576coder
        2
    0576coder  
    OP
       Jul 23, 2021
    @passerbytiny

    对不起 丢人了 我最近 php 也写 java 也写 暴露智商了 半夜脑子转不过来来- -
    zhady009
        3
    zhady009  
       Jul 23, 2021
    因为 Supplier 是没有入参有返回值的方法, Math.random 也是一样 所以可以用静态方法引用
    其他的还有构造器和实例方法
    ztcaoll222
        4
    ztcaoll222  
       Jul 23, 2021
    第一个就是个语法糖,等价于第二个
    unco020511
        5
    unco020511  
       Jul 23, 2021
    第一个和第二个你都可以理解为是语法糖,第三个是原始写法
    mijazz
        6
    mijazz  
       Jul 23, 2021
    上面讲的都蛮清晰暴力了,我来凑个热闹。[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  
       Jul 25, 2021
    第一种是方法引用,第二种 lambda 表达式
    另外第一种与第二种不完全等价,他们具体的实现,是根据不同情况有区别的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   806 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 21:57 · PVG 05:57 · LAX 14:57 · JFK 17:57
    ♥ Do have faith in what you're doing.