方法引用:
创建了函数式接口的匿名内部类对象
重写了函数式接口的抽象方法并在重写的方法中调用被引用的方法
通俗的说,就是用lambda创建了函数式接口的实现类对象,正好lambda要写的抽象体是其他方法的方法体
1.静态方法引用
格式 :
类名::方法名
注意事项:
被引用的方法参数列表和函数式接口中抽象方法的参数一致!!
接口的抽象方法没有返回值,引用的方法可以有返回值也可以没有
接口的抽象方法有返回值,引用的方法必须有相同类型的返回值!!
interface test {
public void run(String string);
}
public class blog {
public static void main(String[] args) {
printString("静态方法引用",System.out::println);
// 实质代码: printString("静态方法引用", (string) -> System.out.println(string));
}
public static void printString(String str, test t) {
t.run(str);
}
}
这个代码中,利用lambda表达式创建了test接口的实现类对象,
重写run()方法,正好方法体是静态方法printString方法
稍微修改一下,将函数式接口抽象方法作为一个有返回值的方法,那么引用方法也得有同样类型的返回值
interface test {
public int run(String string);
}
public class blog {
public static void main(String[] args) {
// 实质代码: getInteger("123", (str) -> Integer.parseInt(str));
int i = getInteger("123", Integer::parseInt);
System.out.println(i); //输出:123
}
public static int getInteger(String str, test t) {
return t.run(str);
}
}
两个例子中,分别调用System.out类的println静态方法,Integer类的parseInt静态方法
由于满足抽象参数列表与引用参数列表相同,所以可以写成静态方法引用的格式
2.对象方法引用
格式:
对象名::非静态方法名
注意事项与静态方法引用完全一致
@FunctionalInterface
interface test {
public String run(String string);
}
class Person {
public String goWalking(String string) {
return string.concat(" 引用方法");
}
}
public class blog {
public static void main(String[] args) {
//实质代码: test t1 = (string) -> new Person().goWalking(string);
//实质代码: System.out.println(t1.run("对象"));
test t2 = new Person()::goWalking;
System.out.println(t2.run("对象")); //输出:对象 引用方法
}
}
类中有一个方法goWalking()方法体是test实现类对象需要的方法体
且方法列表参数一致,返回值类型相同
则可以利用lambda创建test的实现类对象,然后重写的抽象方法体就是调用Person对象的goWalking方法
符合对象引用方法的所有要求,则可以写成t2的样式
3.构造方法引用
格式:
类名::new
注意事项:
被引用的类必须存在一个构造方法与函数式接口的抽象方法参数列表一致
interface test {
public Person1 run(String string);
}
class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
public class blog {
public static void main(String[] args) {
//实质代码: test t1 = (string) -> new Person(string);
//实质代码: Person p = t1.run("张三");
test t2 = Person::new;
Person p2 = t2.run("李四");
System.out.println(p2); //输出:Person{name='李四'}
}
}
由于函数式接口test中抽象方法,返回值是Person对象,且参数列表与Person类中的构造方法相同
则可以通过创建函数式接口的实现类对象,方法体通过调用类中的构造方法创建对象
使用了构造方法引用写成了代码中t2的形式
4.数组构造方法引用
格式:
数据类型[ ]::new
interface test {
public String[] run(int length);
}
public class blog {
public static void main(String[] args) {
//实质代码: test t1 = (length) -> new String[length];
test t2 = String[]::new;
String[] arr = t2.run(5);
}
}
5.特定类型的方法引用
格式:
类名::非静态方法
public class blog {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"d1wdaddq","ASDINAOSDN","aa","AA");
//实质代码: Collections.sort(list,(string1,string2)->string1.compareToIgnoreCase(string2));
Collections.sort(list,String::compareToIgnoreCase);
System.out.println(list);
}
}
特定类型方法引用,在Comparator函数式接口的抽象方法中传入的参数有两个,
可是compareToIgnoreCase()方法参数只有一个,第一个传入的参数作调用对象
这就满足了特定类型的方法引用,所以可以简化成类名::非静态方法的形式
6.类中方法调用父类或本类方法引用
格式:
this::方法名
super::方法名
interface test {
public void itMethod();
}
class father {
public void buy() {
System.out.println("买东西");
}
}
class son extends father {
public void buy() {
System.out.println("买糖");
}
public void test() {
// 实质代码: test t = () -> buy();
test t = this::buy;
t.itMethod();
// 实质代码: test t2 = ()->super.buy();
test t2 = super::buy;
t2.itMethod();
}
}
public class blog {
public static void main(String[] args) {
son s = new son();
s.test(); //输出: 买糖 买东西
}
}
在有继承关系的类中,若方法想调用本类或父类的成员方法
在函数式接口抽象方法与成员方法参数列表相同,且返回值类型相同的情况下
也可以使用this和super的方法引用来简写原本的lambda代码
————————————————
版权声明:本文为CSDN博主「cikinn」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42022555/article/details/81943263