Java 8 引入了一种新的语法,称为方法引用,它可以让你使用简洁的语法来引用一个已存在的方法或构造函数。它有助于减少冗余代码,并使代码更加易读。
方法引用有三种形式:静态方法引用、实例上的方法引用和构造函数引用。
// 静态方法引用 Consumer<String> consumer = System.out::println; consumer.accept("Hello World!"); // 实例上的方法引用 String str = "Hello World!"; Function<String, String> function = str::toUpperCase; System.out.println(function.apply(str)); // 构造函数引用 Supplier<StringBuilder> supplier = StringBuilder::new; System.out.println(supplier.get()); // 输出 "" 空字符串
我们可以通过两种方式获得一个实例方法引用,从对象实例或从类名。
基本上我们有以下两种形式。
这里实例
表示任何对象实例。 ClassName
是的名称类,例如 String
, Integer
。
实例
和 ClassName
称为接收器。更具体地说, instance
被称为有界接收器,而 ClassName
被称为无界接收器。
我们称为实例有界接收器,因为接收器被限制到实例。
ClassName
是未经过排队的接收器,因为接收器以后有界。
绑定接收器接收器具有以下形式:
instance::MethodName
在下面的代码中,我们使用buildin系统函数接口Supplier作为lambda表达式类型。
首先,我们以正常的方式定义一个lambda表达式。 lambda表达式不接受参数,并返回字符串 '.cn' 的长度,
我们使用 '.cn' 创建一个String实例,并使用它的length方法作为实例方法引用。
绑定意味着我们已经指定了实例。
以下示例显示如何使用没有参数的绑定接收器和方法来创建实例方法引用。
import java.util.function.Supplier; public class Main{ public static void main(String[] argv){ Supplier<Integer> supplier = () -> "www..cn".length(); System.out.println(supplier.get()); Supplier<Integer> supplier1 = "www..cn"::length; System.out.println(supplier1.get()); } }
上面的代码生成以下结果。
以下示例显示如何使用绑定接收器和方法与参数创建实例方法引用。
import java.util.function.Consumer; public class Main{ public static void main(String[] argv){ Util util = new Util(); Consumer<String> consumer = str -> util.print(str); consumer.accept("Hello"); Consumer<String> consumer1 = util::print; consumer1.accept("www..cn"); util.debug(); } } class Util{ private int count=0; public void print(String s){ System.out.println(s); count++; } public void debug(){ System.out.println("count:" + count); } }
上面的代码生成以下结果。
未绑定的接收器使用以下语法
ClassName::instanceMethod
它与我们用来引用静态方法的语法相同。
从以下代码,我们可以看到输入类型是ClassName的类型。
在下面的代码中,我们使用 String:length
,因为函数接口的输入类型为 String
。
lambda表达式在使用时获取输入。
以下代码使用String length方法作为unbind实例方法引用。
String length方法通常在字符串值实例上调用,并返回字符串实例的长度。因此,输入是String类型,输出是int类型,这是匹配buildin函数功能接口。
每次我们调用 str Length Func
,我们传入一个字符串值,并从传递的字符串值中调用length方法。
import java.util.function.Function; public class Main{ public static void main(String[] argv){ Function<String, Integer> strLengthFunc = String::length; String name ="www..cn"; int len = strLengthFunc.apply(name); System.out.println("name = " + name + ", length = " + len); name ="www.www..cn"; len = strLengthFunc.apply(name); System.out.println("name = " + name + ", length = " + len); } }
上面的代码生成以下结果。
下面的代码定义了一个具有称为append的静态方法的类Util。
append
方法接受两个 String
类型参数,并返回一个 String
类型的结果。
然后使用 append
方法创建一个lambda表达式并赋值给Java buildin BiFunction
函数接口。
append方法的签名与BiFunction
函数接口中定义的抽象方法的签名相匹配。
import java.util.function.BiFunction; public class Main{ public static void main(String[] argv){ BiFunction<String, String,String> strFunc = Util::append; String name ="www..cn"; String s= strFunc.apply(name,"hi"); System.out.println(s); } } class Util{ public static String append(String s1,String s2){ return s1+s2; } }
上面的代码生成以下结果。
关键字 super
仅在实例上下文中使用,引用覆盖的方法。
我们可以用下面的语法来创建是指在父类型的实例方法的方法引用。
ClassName.super::instanceMethod
下面的代码定义了一个称为 ParentUtil
的父类。在 ParentUtil
中有一个名为 append
的方法,它将两个String值附加在一起。
然后创建一个名为 Util
的子类并扩展 ParentUtil
。
在 Util
类中,覆盖 append
方法。
在Util的构造函数中,我们创建两个lambda表达式,一个是使用Util的append方法,另一个是使用ParentUtil类的append方法。
我们使用 this::append
引用当前类,同时使用 Util.super::append
从父类引用方法。
import java.util.function.BiFunction; public class Main{ public static void main(String[] argv){ new Util(); } } class Util extends ParentUtil{ public Util(){ BiFunction<String, String,String> strFunc = this::append; String name ="www..cn"; String s= strFunc.apply(name," hi"); System.out.println(s); strFunc = Util.super::append; name ="www..cn"; s= strFunc.apply(name," Java Lambda Tutorial"); System.out.println(s); } @Override public String append(String s1,String s2){ System.out.println("child append"); return s1+s2; } } class ParentUtil{ public String append(String s1,String s2){ System.out.println("parent append"); return s1+s2; } }
上面的代码生成以下结果。
Java 实例 - 如何执行指定class文件目录(classpath) Java 实例如果我们 Java 编译后的class文件不在当前目录,我们可以使用 -c...
Java 实例 - 数组填充 Java 实例以下实例我们通过 Java Util 类的 Array.fill(arrayname,value) 方法和 Array.fill(arrayname ,s...
Java IO教程 - Java文件锁NIO支持文件锁定以同步对文件的访问。我们可以锁定文件或整个文件的区域。文件锁定机制由操作系统处理...