栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

02-方法引用、构造器引用、数组引用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

02-方法引用、构造器引用、数组引用

通过 lambda 表达式,我们可以更加优雅的替代匿名内部类,生成一个函数式接口的实例,使我们的编码更加简洁。
这篇文章进一步介绍Java8的新特性,可以让我们的编码相对于 lambda 表达式更为简洁。
分别是:方法引用构造器引用还有数组引用

说白了就是借用别人的轮子。

提示:
这篇文章结合函数式接口lambda表达式进行讲解,Demo中应用了一些Java内置的函数式接口,比如 BiConsumer、BinaryOperator、BiFunction等等。
还不熟悉这个这两个特性,或者对一些Java内置的函数式接口不熟悉的,请看先阅读 01-函数式接口和 lambda 表达式。

若想了解java8其它新特性,请到 00-java8常用新特性文章索引 阅读。

1 方法引用 1.1 方法引用是什么

如果已经有其他类的某一个方法实现了 函数式接口抽象方法需要实现的代码逻辑(lambda 体),可以通过方法引用,直接引用该类已经实现的方法。

简单地讲,只要满足以下条件,即可使用方法引用

    1. 参数列表一样
    1. 返回值一样
    1. lambda体的代码逻辑和目标类成员方法的代码逻辑一样
1.2 方法引用的格式

使用**::**(双冒号)将类名或者对象名和方法名分隔开。

对象::实例方法名
类名::实例方法名
类名::静态方法名

1.3 方法引用怎么用 1.3.1 对象::实例方法名

对象::实例方法名 Demo




public class Calc {

    
    public int add(int x, int y) {
 return x + y;
    }


    
    public static long multi(long x, long y) {
 return x * y;
    }
}


public class MethodRefTest {

    @Test
    public void test00() {

 //lambda表达式
 Consumer cLambda = str -> System.out.println(str);
 // 对象::实例方法名
 Consumer cMethRef = System.out::println;
 cLambda.accept("hello Lambda");
 cMethRef.accept("hello Method Reference");

    }

    @Test
    public void test01() {
 Calc calc = new Calc();
 //lambda表达式
 BinaryOperator oprLambda = (x, y) -> x + y;
 // 对象::实例方法名
 BinaryOperator oprMethRef = calc::add;
 System.out.println(oprLambda.apply(2, 3));
 System.out.println(oprMethRef.apply(2, 3));
    }
}

test00、test01两个测试用例运行结果:

hello Method Reference
hello Method Reference
5
5

1.3.2 类名::实例方法名

类名::实例方法名,这个使用的场景比较特殊,要求第一个参数是实例方法的调用者,剩余的参数都是实例方法的入参,剩余的参数个数可以是0个或者多个。
提示:目标类的实例方法的参数列表会比函数式接口的抽象方法入参个数少一个,因为第一个参数是实例方法的调用者。

public class Person {

    //姓名
    private String name;
    //年龄
    private long age;

    public Person(String name, long age) {
 this.name = name;
 this.age = age;
    }

    public String getName() {
 return name;
    }

    public void setName(String name) {
 this.name = name;
    }

    public long getAge() {
 return age;
    }

    public void setAge(long age) {
 this.age = age;
    }

    @Override
    public String toString() {
 return "Person{" +
  "name='" + name + ''' +
  ", age=" + age +
  '}';
    }

    
    public void sayHello(Person p) {
 System.out.println(this.getName() + " say hello to " + p.getName());
    }
}

public class MethodRefTest {
...
    @Test
    public void test02() {
 //lambda表达式
 BiConsumer bcLambda = (x, y) -> System.out.println(x.getName()+" say hello to "+y.getName());
 // 类名::实例方法名
 BiConsumer bcMethRef = Person::sayHello;
 bcLambda.accept(new Person("P1",18),new Person("P2",18));
 bcMethRef.accept(new Person("P3",18),new Person("P4",18));
    }
    
    @Test
    public void test03() {
 // 判断两个String是否equals
 //lambda表达式
 BiFunction bfLambda = (x, y) -> x.equals(y);
 // 类名::实例方法名
 BiFunction bfMethRef = String::equals;
 System.out.println(bfLambda.apply("a", "b"));
 System.out.println(bfMethRef.apply("a", "a"));

 //求 String 的 hashCode
 //lambda表达式
 Function funcLambda = str -> str.hashCode();
 // 类名::实例方法名
 Function funcMethRef = String::hashCode;
 System.out.println(funcLambda.apply("a"));
 System.out.println(funcMethRef.apply("a"));
    }
}

test02、test03 运行结果:

P1 say hello to P2
P3 say hello to P4
false
true
97
97
1.3.3 类名::实例方法名
    @Test
    public void test04() {
 //lambda表达式
 BinaryOperator bfLambda = (x, y) -> x * y;
 // 类名::静态方法名
 BinaryOperator bfMethRef = Calc::multi;
 System.out.println(bfLambda.apply(2L, 3L));
 System.out.println(bfMethRef.apply(2L, 3L));
    }

    @Test
    public void test05() {
 //lambda表达式
 BinaryOperator bfLambda = (x, y) -> Math.pow(x,y);
 // 类名::静态方法名
 BinaryOperator bfMethRef = Math::pow;
 System.out.println(bfLambda.apply(2D, 3D));
 System.out.println(bfMethRef.apply(2D, 3D));
    }    

test04、test05 运行结果:

6
6
8.0
8.0
2 构造器引用 2.1 构造器引用是什么

构造器引用依然是要结合函数式接口进行使用。
为了简化函数式接口的抽象方法需要实现的代码逻辑(lambda 体),如果lambda体中有返回值,而且返回值类型的构造器参数列表和函数式接口抽象方法的参数列表一致。
这时,就可以使用构造器引用。

看定义,应该看得很懵逼,直接看下面的demo。

2.2 语法格式

类名::new

2.3 构造器引用简单使用
    @Test
    public void test06() {
 //通过函数式接口IntFunction 创建 Integer 实例
 //lambda表达式
 IntFunction intFuncLambda = i -> new Integer(i);
 // 构造器引用:类名::new
 IntFunction intFuncConstRef = Integer::new;
 //lambda表达式生成 函数式接口IntFunction 的实例,执行apply方法后,生成的 Integer 实例
 Integer integerLambda = intFuncLambda.apply(5);
 //构造器引用生成 函数式接口IntFunction 的实例,执行apply方法后,生成的 Integer 实例
 Integer integerConstRef = intFuncConstRef.apply(15);
 System.out.println(integerLambda.intValue());
 System.out.println(integerConstRef.intValue());
    }

    @Test
    public void test07() {
 //通过函数式接口BiFunction 创建 Person 实例
 //lambda表达式
 BiFunction bfLambda = (name, age) -> new Person(name, age);
 // 构造器引用:类名::new
 BiFunction bfConstRef = Person::new;
 // lambda表达式生成的Person
 Person personLambda = bfLambda.apply("张三", 20L);
 // 构造器引用生成的Person
 Person personConstRef = bfConstRef.apply("李四", 25L);
 System.out.println(personLambda);
 System.out.println(personConstRef);
    }

运行结果:

5
15
Person{name='张三', age=20}
Person{name='李四', age=25}
3 数组引用 3.1 是什么

如果你理解了上面的构造器引用,那理解数组引用的使用就很简单了。
构造器引用通过函数式接口的抽象方法调用,使用返回值类型中与函数式接口抽象方法的参数列表一致的构造器,创建一个对象。

数组引用:通过函数式接口的抽象方法调用,将参数作为返回值数组的构造器入参,创建一个数组。

单看这句话应该还是懵逼,下面看一下使用demo。

3.2 语法格式

类名[]:new

3.3 数组引用简单应用
    @Test
    public void test08() {
 // 通过数组引用,生成 String[] 实例
 //lambda表达式
 Function funcLambda = length -> new String[length];
 // 数组引用:类名[]::new
 Function funcArrayRef = String[]::new;
 // lambda表达式生成的String[]
 String[] arrayLambda = funcLambda.apply(2);
 arrayLambda[0] = "lambda";
 // 数组引用生成的String[]
 String[] arrayArrayRef = funcArrayRef.apply(2);
 arrayArrayRef[0] = "Array Reference";
 System.out.println("lambda生成数组:" + Arrays.toString(arrayLambda));
 System.out.println("数组引用生成数组:" + Arrays.toString(arrayArrayRef));
    }

运行结果:

lambda生成数组:[lambda, null]
数组引用生成数组:[Array Reference, null]

方法引用,构造器引用,数组引用都需要结合函数式接口进行使用,当执行函数式接口的抽象方法时,其实调用的是引用类的方法逻辑或者构造器的逻辑,这就是典型的借轮子
使用简单,设计灵巧,但要达到熟练程度,还需要多加理解,学以致用。

代码:
https://github.com/wengxingxia/001java8.git

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号