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中的方法
回顾
- 方法引用的四种方式
 
- 类名::静态方法名
 - 引用名::实例方法名
 - 类名::实例方法名(特殊)
 - 构造方法:类名::new
 
- 什么情况下会实现方法引用:
 
- lambda表达式只有一行方法
 - 恰好这个方法和类中的方法对应
 
除此之外,方法引用是不能使用的。
方法引引用只是lambda的很具体的一种表达方式。
抛出一个问题:
JDK 为什么会有默认方法存在?是为了规避什么问题?
原因: 版本升级,引入默认方法,就是为了保证向后兼容。为了防止版本升级在接口中添加方法,对以前开发的项目实现破坏性的影响。
如List接口中的sort()方法。
JAVA8学习——深入浅出方法引用(学习过程)的更多相关文章
- java8学习之方法引用详解及默认方法分析
		
方法引用: 之前花了很多时间对Lambda表达式进行了深入的学习,接下来开启新的主题---方法引用(Method References),其实在之前的学习中已经使用过了,如: 那方法引用跟Lambda ...
 - JAVA8学习——深入浅出Lambda表达式(学习过程)
		
JAVA8学习--深入浅出Lambda表达式(学习过程) lambda表达式: 我们为什么要用lambda表达式 在JAVA中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法. 在 ...
 - java8新特性——方法引用与构造器引用
		
上篇文章简单学习了java8内置得4大核心函数式接口,这类接口可以解决我们遇到得大多数得业务场景得问题.今天来简单学习一下方法引用与构造器引用. 一.方法引用 方法引用:若lambda 体中得内容已经 ...
 - JAVA8新特性——方法引用
		
JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ 在Lamda新特性的支持下,JAVA8中可以使用lamda表达式来创建匿名方法.然而,有时候我们仅仅是需要调用一个已存在的方法(如 ...
 - Java8 新特性 方法引用
		
什么是方法引用 方法引用可以被看作仅仅调用特定方法的Lamdba表达式的一种快捷方式.比如说Lamdba代表的只是直接调用这个方法,最好还是用名称来调用它,可不用用对象.方法名(),方法引用,引用 ...
 - Java8中的[方法引用]“双冒号”——走进Java Lambda(四)
		
前面的章节我们提及到过双冒号运算符,双冒号运算就是Java中的[方法引用],[方法引用]的格式是 类名::方法名 注意是方法名哦,后面没有括号“()”哒.为啥不要括号,因为这样的是式子并不代表一定会调 ...
 - Java学习笔记-方法引用
		
方法引用(Method Reference) 上一篇中记录了Lambda表达式,其可以创建匿名方法.当Lambda表达式只是调用一个存在的方法时,可以采用方法引用(JDK8具有的特性).如下: pub ...
 - java8新特性-方法引用
		
方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用 (可以将方法引用理解为 Lambda 表达式的另外一种表现形式) 1. 对象的引用 :: 实例方法名2. 类名 :: 静 ...
 - Java8新特性 - 方法引用与构造器引用
		
方法引用 若Lambda体中的内容有方法已经实现了,我们可以使用"方法应用",可以理解为方法引用是Lambda表达式的另外一种表现形式. 使用操作符"::"将方 ...
 
随机推荐
- .NET对接极光消息推送
			
什么是APP消息推送? 很多手机APP会不定时的给用户推送消息,例如一些新闻APP会给用户推送用户可能感兴趣的新闻,或者APP有更新了,会给用户推送是否选择更新的消息等等,这就是所谓的"消息 ...
 - java集合【13】——— Stack源码分析走一波
			
前言 集合源码分析系列:Java集合源码分析 前面已经把Vector,ArrayList,LinkedList分析完了,本来是想开始Map这一块,但是看了下面这个接口设计框架图:整个接口框架关系如下( ...
 - 基于springboot的定时任务实现(非分布式)
			
1. 核心注解 在springboot项目中我们可以很方便地使用spring自己的注解@Scheduled和@EnableScheduling配合来实现便捷开发定时任务. @EnableSchedul ...
 - 网络协议学习笔记(二)物理层到MAC层,交换机和VLAN,ICMP与ping原理
			
概述 之前网络学习笔记主要讲解了IP的诞生,或者说整个操作系统的诞生,一旦有了IP,就可以在网络的环境里和其他的机器展开沟通了.现在开始给大家讲解关于网络底层的相关知识. 从物理层到MAC层:如何在宿 ...
 - 360浏览器兼容模式下jsp页面访问不到js文件
			
360浏览器兼容模式下jsp页面访问不到js文件 查看自己js中的语法问题,不要用ES6的语法,编译不了故找不到js文件 const var of 码出高效 java 比较 所有整型包装类对象之间值的 ...
 - markdownFormat
			
对文档编辑主要还是用wps,因为以前毕业论文都是用的它来编排(刚开始用wps毕业论文的时候真的是用的想吐,感觉非常不好用,而且功能太多但对于自己需要的功能又偏偏找不到),用过几次后还觉得用它编辑文 ...
 - Termux劣质的入门指南
			
直入主题: 1.1 下载安装 Google下载(有条件的用!) F-droid下载(建议使用!) 也可以去酷安下载! 1.2 配置 apt update && apt upgrade ...
 - Netlib文件转化为mps文件
			
Netlib文件转化为mps文件 简单方法1 下载并执行: git clone https://github.com/mtanneau/Netlib_experiments.git cd Netlib ...
 - 【一个idea】YesSql,一种在经典nosql数据库redis上实现SQL引擎的方案(我就要开历史的倒车)
			
公众号链接 最高级的红酒,一定要掺上雪碧才好喝. 基于这样的品味,我设计出了一套在经典nosql数据库redis上实现SQL引擎的方法.既然redis号称nosql,而我偏要把SQL加到redis上, ...
 - visual studio进行机器学习与python编写
			
visual studio里的python安装之后自带一个虚拟环境 1.anaconda有些包版本无法到最新. 2.包管理器在安装卸载,强制停止后,包管理器会出问题,一直卸不掉那个包. 在卸载pyth ...