ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] # 简介 实现抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致. 对象引用: 不同对象操作同一块内容 方法引用: 就是指一个方法设置别名,相当于一个方法定义了不同的名字 **方法引用在java8之中一共定义了四种形式** ~~~ * 引用静态方法: 类名称::static方法名称 * 引用某个对象的方法: 实例化对象::普通方法 * 引用特定类型的方法: 特定类::方法 * 引用构造方法: 类名称::new ~~~ # 方法引用 在使用lambda的时候,我们实际上传递进去的是一种解决方案,拿什么参数做什么操作.那么考虑一种情况. 如果lambda指定的方案,本地已经有,那是否还有必要再写一遍 ~~~ @FunctionalInterface interface Printable { void print(String str); } public class App { public static void main(String[] args) throws InterruptedException { //printString((s) -> System.out.println(s)); printString(System.out::println); } public static void printString(Printable data) { data.print("hello world"); } } ~~~ 注意: lambda传递的参数一定是方法引用中的那个方法可以接收的类型,否则抛异常 ## 引用静态方法 在String类里面有一个valueOf()方法 ~~~ public static String valueOf(int x); ~~~ 案例 ~~~ package com.study; /** * 实现方法的引用类型接口 * @param <P> 引用方法的参数类型 * @param <R> 引用方法的返回类型 */ @FunctionalInterface interface IMessage<P, R> { public R zhuanhuan(P p); } public class HelloWorld { public static void main(String[] args) { // 即: 将String.valueOf()方法变为IMessage接口里面的zhuanhuan()方法 IMessage<Integer, String> msg = String :: valueOf; String str = msg.zhuanhuan(1000); //把0换为9 System.out.println(str.replaceAll("0", "9")); } } ~~~ ## 普通方法引用 ~~~ package com.study; /** * 实现方法的引用类型接口 * @param <P> 引用方法的参数类型 */ @FunctionalInterface //函数式接口 interface IMessage<P> { public P upper(); } public class HelloWorld { public static void main(String[] args) { // String类的toUpperCase()定义: public String toUpperCase() //这个方法没有参数,但是有返回值,并且这个方法一定要在有实例化对象的情况下才可以调用 // "hello"字符串是String类的实例化对象,所有可以直接调用toUpperCase()方法 // 将toUpperCase()函数的应用交给了IMessage接口 IMessage<String> msg = "hello"::toUpperCase; //相当于"hello"::toUpperCase String upper = msg.upper(); System.out.println(upper); } } ~~~ **要实现函数的引用,那么必须要有接口,而且要只存在一个方法** 所有为了保证被引用接口里面只能够有一个方法,那么就需要增加一个注解 ## 类::方法引用普通方法 在进行方法引用的过程里面还有另外一种形式的引用(它需要特定类的对象支持), 正常情况下类::方法,引用的一定是类中的静态方法,但是这种形式也可以引用普通方法 ~~~ 注意:当函数式接口方法的第一个参数是需要引用方法的调用者, 并且第二个参数是需要引用方法的参数(或无参数)时:ClassName::methodName ~~~ ~~~ Employee emp = new Employee(1001, "Jerry", 32, 23430); Function<Employee,String> func1 = (e) -> e.getName(); String name = func1.apply(emp); System.out.println(name); System.out.println("***************"); Function<Employee,String> func2 = Employee::getName; String name1 = func2.apply(emp); System.out.println(name1); ~~~ 例如:String类里面有一个方法: ~~~ public int compareTo(String anotherString) ~~~ 如果要进行比较的话,比较形式: 字符串1对象.compareTo(字符串2对象),要准备出2个参数 例子: 特定类型的引用 ~~~ @FunctionalInterface interface IMessage<P> { public int compare(P p1, P p2); } public class HelloWorld { public static void main(String[] args) { IMessage<String> msg = String::compareTo; //我们可以把前面认为调用对象,后面为传入参数,相对于String::compareTo // public int upper(P p1, P p2); System.out.println(msg.compare("A", "B")); //返回-1.A比B小 } } ~~~ 与之前相比,方法引用前不再需要定义对象,而是可以理解为将对象定义在了参数上 ~~~ BiPredicate<String,String> bi = (s1,s2) -> s1.equals(s2); boolean b = bi.test("abc", "abc"); System.out.println(b); System.out.println("***************"); BiPredicate<String,String> bi1 = String::equals; boolean b1 = bi1.test("abc", "abc"); System.out.println(b1); ~~~ ## 构造方法引用 例如 ~~~ Function<Integer, Myclass> ~~~ ~~~ package com.study; @FunctionalInterface interface IMessage<C> { public C create(String t, double p); } class Book { private String title; private double price; public Book(String title, double price) { this.title = title; this.price = price; } @Override public String toString() { final StringBuilder sb = new StringBuilder("{"); sb.append("\"title\":\"") .append(title).append('\"'); sb.append(",\"price\":") .append(price); sb.append('}'); return sb.toString(); } } public class HelloWorld { public static void main(String[] args) { //引用构造方法 IMessage<Book> msg = Book::new; Book book = msg.create("java", 20.0); System.out.println(book); //输出 {"title":"java","price":20.0} } } ~~~ 对象的引用是使用不同的名字,而方法的引用是需要有一个函数式接口,并且要设置好我们的参数 ## 数组引用 ~~~ Function<Integer,String[]> func1 = (length) -> new String[length]; String[] arr = func1.apply(10); System.out.println(arr.length); System.out.println("**********"); Function<Integer,String[]> func2 = String[]::new; String[] arr1 = func2.apply(20); System.out.println(arr1.length); ~~~ ## super::成员方法 ~~~ /* 使用super引用类的成员方法 super是已经存在的 父类的成员方法sayHello也是已经存在的 所以我们可以直接使用super引用父类的成员方法 */ method(super::sayHello); ~~~ ## this::成员方法 ~~~ /* 使用方法引用优化Lambda表达式 this是已经存在的 本类的成员方法buyHouse也是已经存在的 所以我们可以直接使用this引用本类的成员方法buyHouse */ marry(this::buyHouse); ~~~