理解 Java8 中双冒号 “ :: “ 的用法,方法引用符

在使用 Lambda 表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。试想,有这样一种情况:我们在 Lambda 中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再重写逻辑呢?

当然可以不需要。这时就用到了我们今天要讲解的内容:Java的方法引用符 “::”。

// Lambda 表达式写法:
s -> System.out.println(s);
// :: 方法引用写法:
System.out::println

我么可以通过方法引用,来使用已经存在的方案,使表达式变得更加简洁。


正文

Java 8 中,双冒号 :: 称为“方法引用操作符”,:: 符号为引用运算符,而它所在的表达式被称为方法引用,我们可以使用它来引用类的方法。

:: 引用类的方法,返回一个函数接口(function interface),这等同于 lambda 表达式,但与 lambda 表达式不同的是,lambda表达式需要自定义一个lambda body,而 :: 引用的是一个方法。

/**
* 表示接受一个参数并生成结果的函数。
* @param<T>函数的输入类型
* @param<R>函数结果的类型
* @从1.8开始
*/
@FunctionalInterface
public interface Function<T, R> {
     R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

方法引用操作符有【四种类型】:

  1. ClassName :: New  :对构造函数的引用,相当于创建对象;
  2. ClassName :: static_method :如果有参数会把参数当方法的实参;
  3. ClassName :: instance_method :把第一个参数当做类对象,用来调用 instance_method,其他参数当做方法的参数;
  4. instance :: instance_method :如果有参数会把参数当方法的实参;

案例

下面,简单展示一下 Java引用符四种类型的使用:

import java.util.Arrays;
import java.util.Optional;
import java.util.function.Supplier;

/** 引用操作符的四种类型 */
public class JavaTest {

    public static class User {
        private String id;
        private Integer age;
        private String name;

        // ... 省略了参数的get(),set()方法

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("User{");
            sb.append("id='").append(id).append('\'');
            sb.append(", age=").append(age);
            sb.append(", name='").append(name).append('\'');
            sb.append('}');
            return sb.toString();
        }

        public static void testStatic(String s){
            System.out.println(s);
        }
    }

    /**
     * 1.构造器引用
     *   ClassName::New => new ClassName()
     *   如果调用时有参数,相当于调用带参的构造函数
     */
    @Test
    public void test1(){
        App.toString(User::new);
    }
    public static void toString(Supplier supplier){
        System.out.println(supplier.get().toString());
    }

    /**
     * 2.静态方法引用
     *   ClassName::static_method =》 CLassName.static_method()
     *   如果调用时有参数,直接放到静态方法的形参中
     */
    @Test
    public void test2(){
        Arrays.asList("name1","name2").stream().forEach(User::testStatic);
    }

    /**
     * 3.特定类对方法引用
     *   ClassName::instance_method => obj.instance_method(xxx)
     *   调用时参数:第一个参数是实体对象 上面的obj
     *   如果有其他参数,会传到方法中
     */
    @Test
    public void test3(){
        User user = new User();
        user.setId("625");
        user.setAge(30);
        user.setName("java punk");
        Optional.of(user).ifPresent(User::toString);
    }

    /**
     * 4.特定对象对方法引用
     *   instance::instance_method =》instance.instance_method(xxxx);
     *   如果有参数,参数就是方法的参数
     */
    @Test
    public void test4(){
        User user = new User();
        user.setId("625");
        user.setAge(30);
        user.setName("java punk");
        toString(user::toString);
    }
}

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java Punk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值