方法引用: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()方法。

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

  1. java8学习之方法引用详解及默认方法分析

    方法引用: 之前花了很多时间对Lambda表达式进行了深入的学习,接下来开启新的主题---方法引用(Method References),其实在之前的学习中已经使用过了,如: 那方法引用跟Lambda ...

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

    JAVA8学习--深入浅出Lambda表达式(学习过程) lambda表达式: 我们为什么要用lambda表达式 在JAVA中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法. 在 ...

  3. java8新特性——方法引用与构造器引用

    上篇文章简单学习了java8内置得4大核心函数式接口,这类接口可以解决我们遇到得大多数得业务场景得问题.今天来简单学习一下方法引用与构造器引用. 一.方法引用 方法引用:若lambda 体中得内容已经 ...

  4. JAVA8新特性——方法引用

    JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ 在Lamda新特性的支持下,JAVA8中可以使用lamda表达式来创建匿名方法.然而,有时候我们仅仅是需要调用一个已存在的方法(如 ...

  5. Java8 新特性 方法引用

    什么是方法引用   方法引用可以被看作仅仅调用特定方法的Lamdba表达式的一种快捷方式.比如说Lamdba代表的只是直接调用这个方法,最好还是用名称来调用它,可不用用对象.方法名(),方法引用,引用 ...

  6. Java8中的[方法引用]“双冒号”——走进Java Lambda(四)

    前面的章节我们提及到过双冒号运算符,双冒号运算就是Java中的[方法引用],[方法引用]的格式是 类名::方法名 注意是方法名哦,后面没有括号“()”哒.为啥不要括号,因为这样的是式子并不代表一定会调 ...

  7. Java学习笔记-方法引用

    方法引用(Method Reference) 上一篇中记录了Lambda表达式,其可以创建匿名方法.当Lambda表达式只是调用一个存在的方法时,可以采用方法引用(JDK8具有的特性).如下: pub ...

  8. java8新特性-方法引用

    方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用 (可以将方法引用理解为 Lambda 表达式的另外一种表现形式) 1. 对象的引用 :: 实例方法名2. 类名 :: 静 ...

  9. Java8新特性 - 方法引用与构造器引用

    方法引用 若Lambda体中的内容有方法已经实现了,我们可以使用"方法应用",可以理解为方法引用是Lambda表达式的另外一种表现形式. 使用操作符"::"将方 ...

随机推荐

  1. 如何向内核提交补丁?——FirstKernelPatch

    参考 https://kernelnewbies.org/FirstKernelPatch

  2. Springboot集成邮箱服务发送邮件

    一.前言 Spring Email 抽象的核心是 MailSender 接口,MailSender 的实现能够把 Email 发送给邮件服务器,由邮件服务器实现邮件发送的功能. Spring 自带了一 ...

  3. 【Java常用类】Math

    Math 说明 java.lang.Math提供了一系列静态方法用于科学计算.其方法的参数和返回 值类型一般为double型. 方法 abs 绝对值 acos,asin,atan,cos,sin,ta ...

  4. C#winform控件序列化,反序列化

    using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System. ...

  5. JSP页面使用EL表达式不显示实际数据

    今天在学习有关jsp的相关知识内容时,遇到了el表达式只是显示括号里面的内容 代码如下: <%@ page contentType="text/html;charset=UTF-8&q ...

  6. 字符串工具类ToStringBuilder常用方法介绍

    一.简介与引入   1.ToStringBuilder.HashCodeBuilder.EqualsBuilder.ToStringStyle.ReflectionToStringBuilder.Co ...

  7. Vue.use()用法

    通常我们引入一个第三方组件形式的插件进来时,我们在main.js里面需要Vue.use('该插件名字'),比如引入一个vant组件 那么我们如何自己也来尝试将自己封装的组件以Vue.use()的形式来 ...

  8. DataTable 中文国际化

    DataTable中文设置,详见代码 1 var table = $('#example').DataTable({ 2 "language": { 3 "process ...

  9. Go 变量及基本数据类型3

    #### Go 变量及基本数据类型(三)今天学习一下剩下的两个基本数据类型(布尔类型,字符串类型)以及基本数据类型的相互转换##### 布尔类型布尔类型也称为bool 类型, bool 类型只允许取值 ...

  10. Elasticsearch使用系列-ES增删查改基本操作+ik分词

    Elasticsearch使用系列-ES简介和环境搭建 Elasticsearch使用系列-ES增删查改基本操作+ik分词 一.安装可视化工具Kibana ES是一个NoSql数据库应用.和其他数据库 ...