版权声明:本文为CSDN博主「lkforce」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lkforce/article/details/99682885
lambda表达式的回顾
@FunctionalInterface
public interface ImTheOne {
String handleString(String a, String b);
}
public class Test {
public static void main(String[] args) {
ImTheOne theOne = (a, b) -> a + b;
String result = theOne.handleString("abc", "def");
System.out.println(result);
}
}
方法引用(替换单方法的Lambda表达式)
一、类::静态方法
@FunctionalInterface
public interface ImTheOne {
String handleString(String a, String b);
}
class OneClass {
public static String concatString(String a, String b) {
return a + b;
}
}
public class Test {
public static void main(String[] args) {
ImTheOne theOne = OneClass::concatString;
String result = theOne.handleString("abc", "def");
System.out.println(result);
//相当于以下效果,直接把类的静态方法写在Lambda体里
ImTheOne theOne2 = (a, b) -> OneClass.concatString(a, b);
String result2 = theOne2.handleString("123", "456");
System.out.println(result2);
}
}
二、对象::实例方法
@FunctionalInterface
public interface ImTheOne {
String handleString(String a, String b);
}
class OneClass {
public String concatString(String a, String b) {
return a + b;
}
}
public class Test {
public static void main(String[] args) {
OneClass oneClass = new OneClass();
ImTheOne theOne = oneClass::concatString;
String result = theOne.handleString("abc", "def");
System.out.println(result);
//相当于以下效果
OneClass oneClass2 = new OneClass();
ImTheOne theOne2 = (a, b) -> oneClass2.concatString(a, b);
String result2 = theOne2.handleString("123", "456");
System.out.println(result2);
}
}
三、类::实例方法
当一个对象调用方法时,方法的某个参数是函数式接口,而且函数式接口的方法参数列表的第一个参数就是调用者对象所属的类时,可以引用调用者类中定义的,不包含函数式接口第一个参数的方法,并用类::实例方法这种形式来表达。
@FunctionalInterface
public interface ImTheOne<T> {
String handleString(T t, String b);
default void printString(String s) {System.out.println(s);} // java8新特性
int a = 10;
static int printInteger(int a) {return 3 + a;} // java8新特性
private default void printString2(String s) {System.out.println(s);} // java9新特性
}
class OneClass {
String oneString;
public String concatString(String a) {
return this.oneString + a;
}
public String startHandleString(ImTheOne<OneClass> imTheOne, String str, Integer integer) {
String result = imTheOne.handleString(this, str);
result = result + integer;
return result;
}
}
public class Test {
public static void main(String[] args) {
OneClass oneClass = new OneClass();
oneClass.oneString = "abc";
// 当一个对象(oneClass)调用方法(startHandleString)时,方法的某个参数(ImTheOne)是函数式接口,而且函数式接口的方法参数列表的第一个参数就是调用者对象所属的类(OneClass )时
// 可以引用调用者类中定义的,不包含函数式接口第一个参数(OneClass)的方法(concatString),并用类::实例方法(neClass::concatString)这种形式来表达
String result = oneClass.startHandleString(OneClass::concatString, "123", 456);
System.out.println(result);
//相当于以下效果,这里和OneClass的startHandleString,没有任何关系
OneClass oneClass2 = new OneClass();
oneClass2.oneString = "abc";
ImTheOne theOne2 = (a, b) -> oneClass2.concatString(b);
String result2 = theOne2.handleString(theOne2, "123");
System.out.println(result2);
}
}
函数式接口中的handleString方法参数列表是 (T t, String a,),两个参数,而方法引用中的concatString方法参数是(String a),比handleString少了第一个T参数,此时java会认为第一个参数就是方法的调用者oneClass对象。
四、数组引用,数组::new
@FunctionalInterface
public interface ImTheOne<T> {
// 使用数组引用时,函数式接口中抽象方法必须是有参数的,而且参数只能有一个,必须是数字类型int或Integer,这个参数代表的是将来生成数组的长度。
T getArr(int a);
}
public class Test {
public static void main(String[] args) {
ImTheOne<int[]> imTheOne = int[]::new;
int[] stringArr = imTheOne.getArr(5);
System.out.println(stringArr.length);
}
}
五、构造器引用,Class::new
这种模式被称为构造方法引用,或构造器引用。
构造方法也是方法,构造方法引用实际上表示一个函数式接口中的唯一方法引用了一个类的构造方法,引用的是那个参数相同的构造方法。
@FunctionalInterface
public interface ImTheOne {
// 一个函数式接口中的唯一方法引用了一个类的构造方法,引用的是和那个参数相同的构造方法。
TargetClass getTargetClass(String a);
}
class TargetClass {
String oneString;
public TargetClass() {
oneString = "default";
}
// 函数式接口的方法getTargetClass(String a)有一个String类型的参数,所以当使用构造方法引用时,引用的是有一个String参数的那个构造,也就是这个
public TargetClass(String a) {
oneString = a;
}
}
public class Test {
public static void main(String[] args) {
ImTheOne imTheOne = TargetClass::new;
TargetClass targetClass = imTheOne.getTargetClass("abc");
System.out.println(targetClass.oneString);
//相当于以下效果
ImTheOne imTheOne2 = a -> new TargetClass("def");
TargetClass targetClass2 = imTheOne2.getTargetClass("123"); // 当我们执行这行代码的时候,调用的实际上是Lambda体:new TargetClass("def");。所以输出的是def和123没关系
System.out.println(targetClass2.oneString);
}
}