java8新特性-方法引用

方法引用

方法引用通过方法的名字来指向一个方法。
方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。

当Lambda表达式中只是执行一个方法调用时,不用Lambda表达式,直接通过方法引用的形式可读性更高一些。方法引用是一种更简洁易懂的Lambda表达式。

注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。

四种方法引用类型
1、构造器引用

构造方法引用又分构造方法引用和数组构造方法引用。
构造方法引用(也可以称作构造器引用)
组成语法格式:Class::new
String::new, 等价于lambda表达式 () -> new String()
函数式接口定义方法必须和需要使用构造方法引用类的构造方法参数相同。
如定义一个函数式接口:

public interface IntFuncInterface {
    MyClass func(int i);
}

定义一个需要使用构造方法引用的类

public class MyClass {
    private int i;
    public MyClass(){
        i = 1;
    }
}

此时用如下代码会报错

public static void main(String[] args){
        IntFuncInterface myclass = MyClass::new;
    }

需要在MyClass类中在加一个参数和函数式接口一致的构造函数

public class MyClass {
    private int i;
    public MyClass(){
        i = 1;
    }
    public MyClass(int i){//相同参数的构造方法
        this.i = i;
    }
    public int getI(){
        return this.i;
    }
}

实际调用

public static void main(String[] args){
        //IntFuncInterface myclass = (e)->new MyClass(e);//等价
        IntFuncInterface myclass = MyClass::new;
        MyClass myclassIns = myclass.func(4);
        System.out.println("myclassIns i:"+myclassIns.getI());
    }

输出:

myclassIns i:4

数组构造方法引用
组成语法格式:TypeName[]::new
例子:
int[]::new 是一个含有一个参数的构造器引用,这个参数就是数组的长度。等价于lambda表达式 x -> new int[x]。这个参数不能省略,不然使用TypeName[]::new会报错。
定义一个有参数的函数式接口

public interface IntFuncInterface {
    int[] func(int i);
}

调用

public static void main(String[] args){
       IntFuncInterface intArray = int[]::new;
       int[] a = intArray.func(10);
       System.out.println("a length:"+a.length);
}

输出

a length:10
2、静态方法引用:

组成语法格式:Class::static_method
实例如下:

/**
 * 函数式接口
 */
public interface StringFunc {
    
    String func(String n);
}
public class MyStringOps {
    
    //静态方法: 反转字符串
    public static String strReverse(String str) {
        String result = "";
        for (int i = str.length() - 1; i >= 0; i--) {
            result += str.charAt(i);
        }
        return result;
    }

}
 public static String stringOp(StringFunc sf, String s) {
        return sf.func(s);
    }
    
    public static void main(String[] args) {
        String inStr = "lambda add power to Java";
        //MyStringOps::strReverse 相当于实现了接口方法func() 
        // 并在接口方法func()中作了MyStringOps.strReverse()操作
         String outStr = stringOp(MyStringOps::strReverse, inStr);
        System.out.println("Original string: " + inStr);
        System.out.println("String reserved: " + outStr);
    }

以上strReverse静态方法的参数必须和函数式接口func方法的参数一致。
表达式MyStringOps::strReverse的计算结果为对象引用,其中,strReverse提供了StringFunc的func()方法的实现。

3、特定类的任意对象的方法引用

语法:Class::method;

String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
4、特定对象的方法引用:

这种语法与用于静态方法的语法类似,只不过这里使用对象引用而不是类名。实例方法引用又分以下两种类型:
实例上的实例方法引用
语法:instance::method
例子:反转字符串

/**
 * 函数式接口
 */
public interface StringFunc {
    
    String func(String n);
}
}
public class MyStringOps {
    
    //普通方法: 反转字符串
    public String strReverse1(String str) {
        String result = "";
        for (int i = str.length() - 1; i >= 0; i--) {
            result += str.charAt(i);
        }
        return result;
    }

}
 public static String stringOp(StringFunc sf, String s) {
        return sf.func(s);
    }
    
    public static void main(String[] args) {
        String inStr = "lambda add power to Java";
        MyStringOps strOps = new MyStringOps();//实例对象
        //strOps::strReverse1 相当于实现了接口方法func() 
        String outStr = stringOp(strOps::strReverse1, inStr);
        System.out.println("Original string: " + inStr);
        System.out.println("String reserved: " + outStr);
    }

超类上的实例方法引用
语法:super::methodName;this::methodName;

// 定义一个类
public class Person {
    private String name;
    private int age;

    public Person(){
        name = "";
        age = 0;
    }

    Person changePersonInfo(String name,int age){
        this.age = age;
        this.name = name;
        return this;
    }

    void printPerson(String name,int age){
        InitPersonInterface a = this::changePersonInfo;
        Person person = a.func(name,age);
        System.out.println(person.toString());
    }

    public String toString(){
        return this.name+":"+this.age;
    }

}

//函数式接口
public interface InitPersonInterface {
    Person func(String name,int age);
}
public class PersonDemo extends Person{
    void printPerson(String name,int age){
        InitPersonInterface a = super::changePersonInfo;
        Person person = a.func(name,age);
        System.out.println(person.toString());
    }

    public static void main(String[] args){
        Person p = new Person();
        System.out.println(p.toString());
        p.printPerson("张三",12);
        PersonDemo p1 = new PersonDemo();
        System.out.println(p1.toString());
        p1.printPerson("李四",24);
    }
}

分析:
当有用到类本身或者父类的方法时,可以用this::methodName;super::methodName;来调用。

参考:
https://www.runoob.com/java/java8-method-references.html
https://www.cnblogs.com/xiaoxi/p/7099667.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值