JDK8 新特性之方法引用

一:Lambda的冗余场景

             使用Lambda表达式求一个数组的和

public class Demo11MethodRefIntro {
public static void getMax(int[] arr) {
int sum = 0;
for (int n : arr) {
sum += n;
}
System.out.println(sum);
}
public static void main(String[] args) {
printMax((int[] arr) -> {
int sum = 0;
for (int n : arr) {
sum += n;
}
System.out.println(sum);
});
}
private static void printMax(Consumer<int[]> consumer) {
int[] arr = {10, 20, 30, 40, 50};
consumer.accept(arr);
}
}

   体验方法引用简化Lambda

             如果我们在 Lambda 中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接 引用” 过去就好了
public class DemoPrintRef {
public static void getMax(int[] arr) {
int sum = 0;
for (int n : arr) {
sum += n;
}
System.out.println(sum);
}

//使用方法引用
//让这个指定的方法去重写接口的抽象方法,到时候调用接口的抽象方法就是调用传递过去的这个方法
public static void main(String[] args) {
printMax(Demo11MethodRefIntro::getMax);
}
private static void printMax(Consumer<int[]> consumer) {
int[] arr = {10, 20, 30, 40, 50};
consumer.accept(arr);
}
}
请注意其中的双冒号 :: 写法,这被称为 方法引用 ,是一种新的语法。

方法引用的格式

符号表示 : ::
符号说明 : 双冒号为方法引用运算符,而它所在的表达式被称为 方法引用
应用场景 : 如果 Lambda 所要实现的方案 , 已经有其他方法存在相同方案,那么则可以使用方法引用。

常见引用方式:

方法引用在 JDK 8 中使用方式相当灵活,有以下几种形式:
1. instanceName::methodName 对象 :: 方法名
2. ClassName::staticMethodName 类名 :: 静态方法
3. ClassName::methodName 类名 :: 普通方法
4. ClassName::new 类名 ::new 调用的构造器
5. TypeName[]::new String[]::new 调用数组的构造器

二:对象名::引用成员方法

           这是最常见的一种用法,与上例相同。如果一个类中已经存在了一个成员方法,则可以通过对象名引用成员方法,代码为:
// 对象::实例方法
@Test
public void test01() {
Date now = new Date();
Supplier<Long> supp = () -> {
return now.getTime();
};
System.out.println(supp.get());
Supplier<Long> supp2 = now::getTime;
System.out.println(supp2.get());
}
方法引用的注意事项
1. 被引用的方法,参数要和接口中抽象方法的参数一样
2. 当接口抽象方法有返回值时,被引用的方法也必须有返回值

三:类名::引用静态方法

         由于在 java.lang.System 类中已经存在了静态方法 currentTimeMillis ,所以当我们需要通过 Lambda 来调用该方法时, 可以使用方法引用 , 写法是:
// 类名::静态方法
@Test
public void test02() {
Supplier<Long> supp = () -> {
return System.currentTimeMillis();
};
System.out.println(supp.get());
Supplier<Long> supp2 = System::currentTimeMillis;
System.out.println(supp2.get());
}

四:类名::引用实例方法

              Java 面向对象中,类名只能调用静态方法,类名引用实例方法是有前提的,实际上是拿第一个参数作为方法的调用者。
// 类名::实例方法
@Test
public void test03() {
Function<String, Integer> f1 = (s) -> {
return s.length();
};
System.out.println(f1.apply("abc"));

//类名::实例方法(实际上会将第一个参数作为方法的调用者)
Function<String, Integer> f2 = String::length;
System.out.println(f2.apply("abc"));

//两个参数,一个返回值
BiFunction<String, Integer, String> bif = String::substring;
String hello = bif.apply("hello", 2);
System.out.println("hello = " + hello);
}

五:类名::new引用构造器

            由于构造器的名称与类名完全一样。所以构造器引用使用 类名称 ::new 的格式表示。首先是一个简单的 Person 类:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
要使用这个函数式接口,可以通过方法引用传递:
// 类名::new
@Test
public void test04() {
Supplier<Person> sup = () -> {
return new Person();
};

System.out.println(sup.get());
Supplier<Person> sup2 = Person::new;
System.out.println(sup2.get());
BiFunction<String, Integer, Person> fun2 = Person::new;
System.out.println(fun2.apply("张三", 18));
}

六:数组::new 引用数组构造器

数组也是 Object 的子类对象,所以同样具有构造器,只是语法稍有不同。
// 类型[]::new
@Test
public void test05() {
Function<Integer, String[]> fun = (len) -> {
return new String[len];
};
String[] arr1 = fun.apply(10);
System.out.println(arr1 + ", " + arr1.length);
Function<Integer, String[]> fun2 = String[]::new;
String[] arr2 = fun.apply(5);
System.out.println(arr2 + ", " + arr2.length);
}

小结

                  方法引用是对 Lambda 表达式符合特定情况下的一种缩写,它使得我们的 Lambda 表达式更加的精简,也可以理解为 Lambda表达式的缩写形式 , 不过要注意的是方法引用只能 " 引用 " 已经存在的方法 !
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值