【jdk8新特性】方法引用

简介: 【jdk8新特性】方法引用

【jdk8新特性】方法引用

什么是方法引用,为什么要用方法引用

什么是方法引用

方法引用是为了简化lambda表达式而出现的,表现形式是A::B

为什么要用方法引用

我们来看一个例子就可以理解为什么要用方法引用

// 求一个数组的和
    public static void getMax(int[] arr) {
        int sum = 0;
        for (int n : arr) {
            sum += n;
        }
        System.out.println(sum);
    }

    public static void main(String[] args) {
        // 使用Lambda表达式求一个数组的和
        /*printMax((int[] arr) -> {
            getMax(arr);
        });*/ // 例子一

        // 使用方法引用
        // 让这个指定的方法去重写接口的抽象方法,到时候调用接口的抽象方法就是调用传递过去的这个方法
        printMax(Demo01MethodRefIntro::getMax);// 例子二
    }

    public static void printMax(Consumer<int[]> consumer) {
        int[] arr = {11, 22, 33, 44, 55};
        consumer.accept(arr);
    }
}

我们可以看到我们有一个getMax方法进行数组求和运算,此时我们使用Lambda表达式来进行数组求和,可以看到第一个例子它用lambda调用了 getMax方法 但这样那我为什么不直接用getMax方法呢?所以我们有了例子二:利用类::方法名 来用作方法引用,即把方法名对应的方法 重写到accept方法。

常见引用方式

方法引用在JDK 8中使用方式相当灵活,有以下几种形式:

  1. instanceName::methodName 对象::方法名
  2. ClassName::staticMethodName 类名::静态方法
  3. ClassName::methodName 类名::普通方法
  4. ClassName::new 类名::new 调用的构造器
  5. TypeName[]::new String[]::new 调用数组的构造器

其中3:类名::普通方法,按传统语法的理解是错误的,这里进行了处理

对象名::引用成员方法

// 对象::实例方法
@Test
public void test01() {
    Date now = new Date();

    /*Supplier<Long> su1 = () -> {
            return now.getTime();
        };*/

    // 使用方法引用
    Supplier<Long> su1 = now::getTime;

    Long aLong = su1.get();
    System.out.println("aLong = " + aLong);
}

这里我们使用了Date类的实例对象 now进行方法引用

补充注意点

注意:方法引用有两个注意事项

 1.被引用的方法,参数要和接口中抽象方法的参数一样
 2.当接口抽象方法有返回值时,被引用的方法也必须有返回值
         Supplier<Long> su3 = now::setTime;// 错误
         su3.get();

​ Supplier su4 = now::setDate;
​ su4.get();

可以看出setTime与setDate都需要参数且不需要返回值,但get方法是由返回值不需要参数,因为本质是重写get方法,但现在参数、返回值 不匹配所有不能这样写。

类名::引用静态方法

// 类名::静态方法
@Test
public void test02() {
    /*Supplier<Long> su = () -> {
        return System.currentTimeMillis();
    };*/

    Supplier<Long> su = System::currentTimeMillis;

    Long time = su.get();
    System.out.println("time = " + time);
}

类名::引用实例方法

// 类名::实例方法
@Test
public void test03() {
    /*Function<String, Integer> f1 = (String str) -> {
        return str.length();
    };*/

    // 类名::实例方法(注意:类名::类名::实例方法实际上会将第一个参数作为方法的调用者)
    Function<String, Integer> f1 = String::length;

    int length = f1.apply("hello");// 调用的实际是"hello".length()
    System.out.println("length = " + length);

    // BiFunction<String, Integer, String> f2 = String::substring;
    // 相当于这样的Lambda
    BiFunction<String, Integer, String> f2 = (String str, Integer index) -> {
        return str.substring(index);
    };
    String str2 = f2.apply("helloworld", 3);// 相当于"helloworld".substring(3);
    System.out.println("str2 = " + str2); // loworld
}

Java面向对象中,类名只能调用静态方法,类名引用实例方法是有前提的,实际上是拿第一个参数作为方法的调用者。

类名::new引用构造器

// 类名::new引用类的构造器
@Test
public void test04() {
    /*Supplier<Person> su1 = () -> {
        return new Person();
    };*/

    Supplier<Person> su1 = Person::new;

    Person person = su1.get();
    System.out.println("person = " + person);

    /*BiFunction<String, Integer, Person> bif = (String name, Integer age) -> {
        return new Person(name, age);
    };*/
    BiFunction<String, Integer, Person> bif = Person::new;
    Person p2 = bif.apply("凤姐", 18);
    System.out.println("p2 = " + p2);
}

Person类

public class Person {
    private String name;
    private int age;

    public Person() {
        System.out.println("执行无参构造");
    }

    public Person(String name, int age) {
        System.out.println("执行有参构造: " + name + ", " + age);
        this.name = name;
        this.age = age;
    }
}

由于构造器的名称与类名完全一样。所以构造器引用使用 类名称::new 的格式表示。

数组::new 引用数组构造器

// 类型[]::new
@Test
public void test05() {
    /*Function<Integer, int[]> f1 = (Integer length) -> {
        return new int[length];
    };*/

    Function<Integer, int[]> f1 = int[]::new;

    int[] arr1 = f1.apply(10);
    System.out.println(Arrays.toString(arr1));
}

数组也是 Object 的子类对象,所以同样具有构造器,只是语法稍有不同。

目录
相关文章
|
2月前
|
安全 JavaScript 前端开发
JDK1.8的重要的新特性与功能
Java Development Kit (JDK) 1.8,也称为Java 8,是Java平台的一个重大更新,于2014年3月发布。它引入了多项新特性、新的API和性能提升
75 3
|
3月前
|
监控 安全 Java
探索Java的未来:JDK 18新特性全览
探索Java的未来:JDK 18新特性全览
80 0
|
3月前
|
缓存 安全 Java
JDK 14全景透视:每个Java开发者必知的新特性
JDK 14全景透视:每个Java开发者必知的新特性
54 0
|
6天前
|
算法 Java 编译器
升级指南之JDK 11+ 新特性和AJDK
本文详细介绍了JDK个版本之间的特性、区别以及JDK版本更迭时优化了哪些地方,对JDK的版本选择给出了建议,以及升级教程。
|
12天前
|
存储 安全 Java
JDK22发布了!来看看有哪些新特性
以上是介绍 JDK22新特性的全部内容了,突然V哥想要感慨一下,技术之路,学无止境,选择 IT 技术,作个纯粹的人,享受研究技术的过程,这种带来的快感,也许只有真正热爱编程的人才能有体会。
|
2月前
|
编解码 Java API
集合在JDK9中的新特性
集合在JDK9中的新特性
|
2月前
|
Java
JDK8新特性--lambda表达式
面向对象思想强调:必须通过对象的形式来做事情
JDK8新特性--lambda表达式
|
2月前
|
SQL Java API
浅析jdk8所包含的主要特性
浅析jdk8所包含的主要特性
|
3月前
|
前端开发 IDE Java
JDK 新特性学习笔记之模块系统
JDK 新特性学习笔记之模块系统
|
3月前
|
安全 网络协议 Java
JDK 16全览:改变游戏规则的新特性
JDK 16全览:改变游戏规则的新特性
44 0