首页 > 编程语言 >java8新特性:方法引用

java8新特性:方法引用

时间:2022-09-07 14:12:54浏览次数:69  
标签:特性 Person 引用 new 方法 java8 表达式 Lambda

java8新特性:方法引用

我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它,而Lambda表达式可以帮助我们实现这一要求,它使得Lambda在调用那些已经拥有方法名的方法的代码更简洁、更容易理解。方法引用可以理解为Lambda表达式的另外一种表现形式。

在Lambda表达式中,将其划分了几块。这一行就是lambda表达式。

() -> System.out.println("使用Lambda表达式");

下面我们对lambda的格式进行一个介绍:

(1)左边括号:lambda的形参列表,就好比是我们定义一个接口,里面有一个抽象方法,这个抽象方法的形参列表。

(2)箭头:lambda的操作符,所以你看见这个箭头心中知道这是一个lambda表达式就可以了。

(3)右边lambda体:就好比是我们实现了接口中的抽象方法。

在最后一块中,有时候,lambda体可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰。

所以我们来总结:方法引用是一个更加紧凑,易读的 Lambda 表达式,注意方法引用是一个 Lambda 表达式,其中方法引用的操作符是双冒号 "::"

类型语法对应的Lambda表达式
静态方法引用 类名::staticMethod (args) -> 类名.staticMethod(args)
实例方法引用 inst::instMethod (args) -> inst.instMethod(args)
对象方法引用 类名::instMethod (inst,args) -> 类名.instMethod(args)
构建方法引用 类名::new (args) -> new 类名(args)

方法引用举例

静态方法引用

  有一个Person类,如下所示:

@Data  //用了注解后,setter/getter, 构造函数,toString,hashCode,equals方法由框架生成
public class Person {
​
    private String name;
​
    private Integer age;
​
    //静态方法
    public static int compareByAge(Person a, Person b) {
        return a.age.compareTo(b.age); //两个年龄比大小
    }
}

 

  现假设,一个部门有30人,把他们存放在一个数组中,并按年龄排序,通常我们可以自己写一个比较器,代码如下:

Person[] rosterAsArray = new Person[30];
// 添加数组元素省略
​
class PersonAgeComparator implements Comparator<Person> {
    public int compare(Person a, Person b) {
        return a.getBirthday().compareTo(b.getBirthday());
    }
}
​
Arrays.sort(rosterAsArray, new PersonAgeComparator());

  Arrays.sort的声明为:public static <T> void sort(T[] a, Comparator<? super T> c),比较器参数Comparator为一个函数式接口,利用上一节Lambda表达式所学知识,可以改写为以下代码:

Person[] rosterAsArray = new Person[30];
// 添加数组元素省略
Arrays.sort(rosterAsArray, (a,b) -> a.getAge().compareTo(b.getAge()));

  然而,你会发现,Perdon类中已经有了一个静态方法的比较器:compareByAge,因此,我们改用Person类已经提供的比较器:

Person[] rosterAsArray = new Person[30];
// 添加数组元素省略 
Arrays.sort(rosterAsArray, (a,b) -> Person.compareByAge(a,b));

  以上代码,因为Lambda表达式调用了一个已经存在的静态方法,根据我们第2节表格中的语法,上面的代码可以最终改写成静态方法引用:

Person[] rosterAsArray = new Person[30];
// 添加数组元素省略
Arrays.sort(rosterAsArray, Person::compareByAge);

  下面这个例子更简单:

public class Test {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(82,22,34,50,9);
        list.sort(Integer::compare);
        System.out.println(list);
    }
 }

 

  对一个Integer列表进行排序,因为Integer中已经存在静态的比较方法compare(),因此可以直接用静态方法引用的方式来调用 ,运行结果为:

[9, 22, 34, 50, 82]

实例方法引用

  实例方法引用,顾名思义就是调用已经存在的实例的方法,与静态方法引用不同的是类要先实例化,静态方法引用类无需实例化,直接用类名去调用。

 @Data
 class User {
 
     private String name;
     private Integer age;
 
     public User(String name, Integer age) {
         this.name = name;
         this.age = age;
     }
 }
 
 public class TestInstanceReference {
 
     public static void main(String[] args) {

         TestInstanceReference test = new TestInstanceReference();
         User user = new User("欧阳峰",32);
         
         Supplier<String> supplier = () -> user.getName();//Supplier的get方法的匿名实现
         System.out.println("Lambda表达式输出结果:" + supplier.get());
 
         /*
         user::getName本质是Supplier接口中的抽象get方法的匿名实现
         */
         Supplier<String> supplier2 = user::getName;
         System.out.println("实例方法引用输出结果:" + supplier2.get());
     }
 }

  输出结果:

Lambda表达式输出结果:欧阳峰
实例方法引用输出结果:欧阳峰

对象方法引用

  若Lambda参数列表中的第一个参数是实例方法的参数调用者,而第二个参数是实例方法的参数时,可以使用对象方法引用。

String的equals()方法:

  public boolean equals(Object anObject) {
          if (this == anObject) {
              return true;
          }
          if (anObject instanceof String) {
              String anotherString = (String)anObject;
              int n = value.length;
              if (n == anotherString.value.length) {
                  char v1[] = value;
                  char v2[] = anotherString.value;
                  int i = 0;
                  while (n-- != 0) {
                      if (v1[i] != v2[i])
                          return false;
                      i++;
                  }
                  return true;
              }
          }
          return false;
      }
 public static void main(String[] args) {
 
    BiPredicate<String,String> bp = (x, y) -> x.equals(y);
    BiPredicate<String,String> bp1 = String::equals;
 
    boolean test = bp1.test("xy", "xx");
    System.out.println(test);
 }

  BiPredicate的test()方法接受两个参数,x和y,具体实现为x.equals(y),满足Lambda参数列表中的第一个参数是实例方法的参数调用者,而第二个参数是实例方法的参数,因此可以使用对象方法引用。

构造方法引用

  注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致。

  如:要获取一个空的User列表:

 Supplier<List<User>> userSupplier = () -> new ArrayList<>();
 List<User> user = userSupplier.get();
 
 Supplier<List<User>> userSupplier2 = ArrayList<User>::new;    // 构造方法引用写法
 List<User> user2 = userSupplier.get();

 

标签:特性,Person,引用,new,方法,java8,表达式,Lambda
From: https://www.cnblogs.com/huang2979127746/p/16665212.html

相关文章

  • Java8Stream流复习和api总结
    构建方式list.stream();Stream.of(list);基础常用APIStream<Number>stream=list.stream();//获取最大值stream.max(比较器);//获取最小值stream.min(比较器);......
  • [记]Rust可变引用与不可变引用
    --->fnmain(){letmutvar=0_i32;{letp1=&mutvar;//p1指针本身不能被重新绑定,我们可以通过p1改变变量var的值*p1=1;pr......
  • 引用计数的存储
    在64位中,引用计数可以直接存储在优化过的isa指针中,也可能存储在SideTable类中。在isa里面,有一个extra_rc参数其中:rc就是retainCount引用计数的意思。则has_sidetable_r......
  • vue前端项目组件实现自动注册并且全局可引用
     1、首先创建一个组件的目录,例如图中components2、创建一个js主文件和一个存放组件的目录如global3、在js中加入图中代码,实现自动识别组件功能4、在文件入口main.js......
  • vue3 基础-non-props 特性
    本篇探讨当父组件通过属性给子组件传数据时,子组件如果不通过props属性进行接收,那数据会挂载到哪里,以及子组件如何能使用这些数据.正常的父子组件传值<!DOCTYPEh......
  • TCP传输层协议 特性
    TCP特性:1、工作在传输层2、面向连接3、全双工协议4、半开关5、错误检查6、将数据包打包成断,排序7、确认机制8、数据恢复,重传9、流量控制,滑动窗口更多关于tcp的内......
  • HTML5新标签与特性
    1.HTML5新标签与特性达标:掌握html5的常用新标签-新属性1.1什么是HTML5HTML5:HTML标准的最新版本,是对HTML的第五次重大修改。HTML5的出现,对于WEB来说意义重大,其目的......
  • TS创建接口和接口类型数组,并统一导入后引用
    在app.ts中引用import{users,IRoute,IUser,routes}from"./data";在index.ts中统一导入后导出export*from"./routes";export*from"./users";importro......
  • delphi 各新版本特性收集(转)
    DelphiXE6新增了一些特性并增强了原有的功能,主要有以下几个方面: IDE(整合开发环境) InternetXML(扩展标记语言)Compiler(编译器)COM/ActiveXDatabasesupport(数据库......
  • angular如何引用其他组件
    原文链接:angular如何引用其他组件–每天进步一点点(longkui.site)   0.背景前面一篇文章,简单介绍过angular创建并引用组件。在实际情况开发中,情况会稍微......