JAVA8学习——深入浅出方法引用(学习过程)

方法引用:method reference

先简单的看一下哪里用到了方法引用:

public class MethodReferenceTest {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "world", "hello world");

//        list.forEach(item -> System.out.println(item));

        list.forEach(System.out::println);
    }
}

方法引用实际上是lambda表达式的一种语法糖

我们可以将方法引用看做一个「函数指针」,function pointer

方法引用共分为4类:

下面会逐步介绍四种类型,并且用代码实现:公用的Student类如下

package com.dawa.jdk8.methodreference;

public class Student {
    private String name;
    private int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

//这两个方法,只是测试时候使用。实际设计有问题
    public static int compareStudenyByScore(Student student, Student student2) {
        return student.getScore() - student2.getScore();
    }

    public static int compareStudenyByName(Student student, Student student2) {
        return student.getName().compareToIgnoreCase(student2.getName());
    }

    //这样设计才比较合理。
    public int compareByScore(Student student) {
        return this.score - student.getScore();
    }

    public int compareByName(Student student) {
        return this.name.compareToIgnoreCase(student.getName());
    }

}

1. 类名::方法名.

  • 具体实现:
public class MethodReferenceTest {
    public static void main(String[] args) {

        Student student1 = new Student("dawa", 20);
        Student student2 = new Student("erwa", 80);
        Student student3 = new Student("sanwa", 60);
        Student student4 = new Student("siwa", 40);

        List<Student> list = Arrays.asList(student1, student2, student3, student4);

//        list.sort((studentParam1, studentParam2) -> Student.compareStudenyByScore(studentParam1, studentParam2));
        list.sort(Student::compareStudenyByScore);
        list.forEach(item-> System.out.println(item.getScore()));

//        list.sort((studentParam1, studentParam2) -> Student.compareStudenyByName(studentParam1, studentParam2));
        list.sort(Student::compareStudenyByName);
        list.forEach(item-> System.out.println(item.getName()));

    }
}

2. 引用名(对象)::实例方法名

和第一种方法类似

定义一个实例:
package com.dawa.jdk8.methodreference;

public class StudentComparator {

    public int compareStudentByScore(Student student1, Student student2) {
        return student1.getScore() - student2.getScore();
    }

    public int compareStudentByName(Student student1, Student student2) {
        return student1.getName().compareToIgnoreCase(student2.getName());
    }
}

具体实现:

StudentComparator studentComparator = new StudentComparator();
//list.sort((studentParam1,studentParam2) ->studentComparator.compareStudentByName(studentParam1,studentParam2));
list.sort(studentComparator::compareStudentByScore);
list.sort(studentComparator::compareStudentByName);

3.类名::实例方法名

list.sort(Student::compareByScore);
list.sort(Student::compareByName);
//方法是谁来调用的?
//一定是 sort方法里面的lambda表达式的第一个参数来调用的compareByScore 实例方法
//而lambda表达式的后续参数,都将作为这个实例方法的参数

//扩展
List<String> cities = Arrays.asList("chengdu", "beijing", "shanghai", "chongqing");
//Collections.sort(cities,(value1,value2)->value1.compareToIgnoreCase(value2));
cities.sort(String::compareToIgnoreCase);
cities.forEach(System.out::println);
  • 额外知识点扩展:

System.out这个类中的out参数是null;赋值是通过最上面的函数registerNatives():底层是通过C来通过底层GNI实现的。
因为输入输出设备本身是跟硬件相关的。所以用通过底层的C来完成的。
Out,In,err 等几个参数都是如此。

public final class System {

    /* register the natives via the static initializer.
     *
     * VM will invoke the initializeSystemClass method to complete
     * the initialization for this class separated from clinit.
     * Note that to use properties set by the VM, see the constraints
     * described in the initializeSystemClass method.
     */
    private static native void registerNatives();
    static {
        registerNatives();
    }
...

4. 构造方法引用:类名::new

实际上就够调用了构造方法来生成一个new对象。

    public String getStr(Supplier<String> supplier) {
        return supplier.get() + "test";
    }

    public String getString(String str, Function<String, String> function) {
        return function.apply(str);
    }

    //在main方法中调用
    MethodReferenceTest methodReferenceTest = new MethodReferenceTest();
    methodReferenceTest.getStr(String::new);
    methodReferenceTest.getString("hello", String::new);

默认方法

用案例再次解释默认方法

如果有两个接口,分别的默认方法签名都相同,都被一个类继承

类里面需要使用 Interface.super.method()来声明你要使用哪个方法。不然会编译器报错。

public interface MyInterface1 {
    default void mymethod1(){
        System.out.println("mymethod1");
    }
}

public interface MyInterface2 {
    default void mymethod1(){
        System.out.println("mymethod2");
    }
}

//如下
public class MyClass implements MyInterface1,MyInterface2 {
    @Override
    public void mymethod1() {
        MyInterface2.super.mymethod1();
    }

    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.mymethod1();
    }
}

另外:如果一个类,继承了接口1的实现类,又实现了接口2
那么:默认调用实现类里面的方法。这是没有错的
因为:JAVA认为实现类更为具体,接口只是类的契约。默认
所以:类中调用的是接口1中的方法

回顾

  • 方法引用的四种方式
  1. 类名::静态方法名
  2. 引用名::实例方法名
  3. 类名::实例方法名(特殊)
  4. 构造方法:类名::new
  • 什么情况下会实现方法引用:
  1. lambda表达式只有一行方法
  2. 恰好这个方法和类中的方法对应

    除此之外,方法引用是不能使用的。
    方法引引用只是lambda的很具体的一种表达方式。

抛出一个问题:

JDK 为什么会有默认方法存在?是为了规避什么问题?

原因: 版本升级,引入默认方法,就是为了保证向后兼容。为了防止版本升级在接口中添加方法,对以前开发的项目实现破坏性的影响。
如List接口中的sort()方法。

原文地址:https://www.cnblogs.com/bigbaby/p/12150699.html

时间: 2024-10-30 11:15:37

JAVA8学习——深入浅出方法引用(学习过程)的相关文章

JAVA8学习——深入浅出Lambda表达式(学习过程)

JAVA8学习--深入浅出Lambda表达式(学习过程) lambda表达式: 我们为什么要用lambda表达式 在JAVA中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法. 在JavaScript中,函数参数是一个函数,返回值是另一个函数的情况下非常常见的,JavaScript是一门非常典型的函数式编程语言,面向对象的语言 //如,JS中的函数作为参数 a.execute(callback(event){ event... }) Java匿名内部类实例 后面补充一个匿名内

JAVA8新特性——方法引用

JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ 在Lamda新特性的支持下,JAVA8中可以使用lamda表达式来创建匿名方法.然而,有时候我们仅仅是需要调用一个已存在的方法(如java中已经定义好的方法),在这时候java8新特性"方法引用"将会进一步简化操作(注意:需要有Lamda的支持). 方法引用的四种形式: 引用静态方法-->类名称::static 方法名称: 引用某个对象的实例的普通方法-->示例化对象::普通方法: 引用某个类型的任意对象

java8中的方法引用与构造器引用

java8中的方法引用与构造器引用 方法引用:若Lambda体中的内容有方法已经实现了,我们可以使用"方法引用" 主要的三种语法格式: 对象::实例名 类::静态方法名 类::实例方法名 注意: Lmabda体中调用方法的参数列表与返回值类型要与函数式接口中抽象方法的函数列表和返回值类型保持一致 若Lambda参数列表中的第一参数是 实例方法的调用者,而第二个参数是 实例方法的参数时,可以使用ClassName::method public class Employee { priva

Java学习笔记-方法引用

方法引用(Method Reference) 上一篇中记录了Lambda表达式,其可以创建匿名方法.当Lambda表达式只是调用一个存在的方法时,可以采用方法引用(JDK8具有的特性).如下: 1 public class Person { 2 3 public enum Sex { 4 MALE, FEMALE 5 } 6 7 String name; 8 LocalDate birthday; 9 Sex gender; 10 String emailAddress; 11 int age;

Java8学习笔记(二)-函数式接口与方法引用

一.Lambada表达式到底是什么 首先先看一下下面的一段代码! package cn.org.kingdom.jdk8; @FunctionalInterface interface MyInterface { void test(); String toString(); } public class Test { public void test(MyInterface inter) { System.out.println("*************************"

JAVA8学习——从使用角度深入Stream流(学习过程)

Stream 流 初识Stream流 简单认识一下Stream:Stream类中的官方介绍: /** * A sequence of elements supporting sequential and parallel aggregate * operations. The following example illustrates an aggregate operation using * {@link Stream} and {@link IntStream}: * * <pre>{@

Java8之方法引用

一.概述 在学习lambda表达式之后,我们通常使用lambda表达式来创建匿名方法.然而,有时候我们仅仅是调用了一个已存在的方法.如下: Arrays.sort(stringsArray,(s1,s2)->s1.compareToIgnoreCase(s2)); 在Java8中,我们可以直接通过方法引用来简写lambda表达式中已经存在的方法. Arrays.sort(stringsArray, String::compareToIgnoreCase); 这种特性就叫做方法引用(Method

Java8 方法引用

概述方法引用是用来直接访问类或实例×××存在的方法或者构造方法.它需要由兼容的函数式接口(lambda表达式中用到的接口)构成的目标类型上下文. 有时候, 当我们想要实现一个函数式接口的方法, 但是已经由类实现了我们想要的功能, 这时可以使用方法引用来直接使用现有的功能实现. 关于lambda表达式可以看这篇文章Java8 Lambda表达式 当lambda表达式只是执行一个方法调用时, 直接通过方法引用的形式调用. 方法引用是一种更简洁的lambda表达式. 方法引用是lambda表达式的简写

java8之lambda表达式(方法引用)

有些时候,你想要传递给其他代码的操作已经有实现的方法了.示例: button.setOnAction(event -> System.out.println(event); 如果你能够只将println方法传递给setOnAction方法,就更好了!下面是改后的代码: button.setOnAction(System.out::println); 表达式System.out::println是一个方法引用,等同于lambda表达式: x -> System.out.println(x) 正如