lambda表达式——类名::实例方法

最近看了lambda表达式的用法,看到方法引用,类名::静态方法和实例::实例方法都好理解,Demo实现也比较简单,但是看到公司代码有 类名::实例方法 的使用,比较疑惑,自己写了些Demo都没法实现,看了多篇博客找到这篇比较好的,记录一下。

方法引用总共有如下四种类型,这里只介绍第三种,其余三种都较为简单,如有需要,请参见他人博客。

类型示例
引用对象的实例方法Object::instanceMethodName
引用类的静态方法ClassName::staticMethodName
引用类的实例方法ClassName::methodName
引用构造方法ClassName::new

第三种引用类的实例方法???这个名字相当的不准确,在Java 8 In Action是这样介绍的,指向任意类型实例方法的方法引用(我觉得叫类的任意对象的实例方法引用更直观)。我开始一直想当然的就认为是类::实例方法这样就可以了,结果写了几个发现都用不了,看了官网给出的示例发现又可以,于是,作为当代优秀青年,怎么可能不解决这个问题呢。

官网给出的示例:

String [] stringArray = {“芭芭拉”,“詹姆斯”,“玛丽”,“约翰”,
    “Patricia”,“Robert”,“Michael”,“Linda”};
Arrays.sort(stringArray,String :: compareToIgnoreCase);

方法引用的等效lambda表达式String::compareToIgnoreCase将具有形式参数列表(String a, String b),其中a和b是用于更好地描述此示例的任意名称。方法引用将调用该方法a.compareToIgnoreCase(b)。我反正是没看懂这是讲的啥。之后再查了下,原文是这样的 “ reference to an instance method of an arbitrary object of a particular type ” arbitrary 任意的, particular 特定的,翻译过来就是引用特定类型的任意对象的实例方法。于是乎,知道了类的实例方法调用是有讲究的。那么,有什么样的条件呢。

public class test1 {
    public static void main(String[] args) {
 
        List<Student> list = new ArrayList<>();
        list.add(new Student("Jack1", 88));
        list.add(new Student("Jack2", 81));
        list.add(new Student("Jack3", 82));
        list.add(new Student("Jack4", 83));
        list.add(new Student("Jack5", 84));
        list.add(new Student("Jack6", 85));
        list.sort(Student::compareByScore);
        System.out.println(list);
    }
}
 
class Student {
    private String name;
    private int score;
 
    public Student(){
 
    }
 
    public Student(String name,int score){
        this.name = name;
        this.score = score;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getScore() {
        return score;
    }
 
    public void setScore(int score) {
        this.score = score;
    }
 
    public int compareByScore(Student student){
        return this.getScore() - student.getScore();
    }
 
    @Override
    public String toString(){
        return this.name + "  " + this.score + "  ";
    }
}

list.sort接受一个Comparator,Comparator需要实现compare方法,lambda形式 (v1,v2)-> {dosth;return intval;}。这里的compareByScore就是这种lambda形式的方法引用。

如果将上面的compareByScore方法改成如下形式,为什么又要报错了,我不就多传了一个参数进去么,其他的啥也没做啊。

 public int compareByScore(Student student1, Student student2){
        return this.getScore() - student1.getScore();
    }

不好意思,它要求接口方法的参数必须比引用方法的参数多一个。而且第一个参数要是该引用方法的所在类型的或其父类,除接口方法的第一个参数以外, 其余参数的类型要求一样。这一段话,有些难以理解,看下面的代码就会明白了。

example 1

public  class Test1 {
    public void a(){
    }
    public static void main(String[] args) {
        MyInter m = Test1::a;
    }
}
@FunctionalInterface
interface MyInter {
    //入参参数比Test1的a方法多一个,且Test1::a的Test1与该入参类型Test1相同
    public void d(Test1 d);
}

example 2

public  class Test1 {
    public void a(Integer param1,int param2){
    }
    public static void main(String[] args) {
        MyInter m = Test1::a;
    }
}
@FunctionalInterface
interface MyInter {
    //该接口参数比上述的a方法参数数量多一个,除去第一个,其它类型一致(可兼容,如可以一个int,一个Integer)
    //且Test1::a的Test1是该入参类型Test1相同
    public void d(Test1 d,int param1,int param2);
}

example 3

public  class Test1 {
    public void a(Integer param1,int param2){
    }
    public static void main(String[] args) {
        MyInter m = Test1::a;
    }
}
class Test2 extends Test1 {
}
@FunctionalInterface
interface MyInter {
    //该接口参数比上述的a方法参数数量多一个,除去第一个,其它类型一致(可兼容,如可以一个int,一个Integer)
    //且Test1::a的Test1是该入参类型Test2的子类(不可颠倒)
    public void d(Test2 d,int param1,int param2);
}

example 4

public  class Test1 {
    public void a(Integer param1,int param2){
    }
    public static void main(String[] args) {
        MyInter m = (j,k,l)->j.a(k, l);
        //第一个参数为方法目标,其余参数为参数
    }
}
@FunctionalInterface
interface MyInter {
    public void d(Test1 d,int param1,int param2);
}

看到这你应该就懂了,这个指向任意类型实例方法的方法引用有两个要求:

   第一点:接口方法的参数比引用方法的参数多一个
   第二点:接口方法的第一个参数恰巧是调用引用方法的对象(其引用方法所在类或其父类的实例)
   如有不当之处,望指正。

参考文献:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
https://stackoverflow.com/questions/32855138/how-does-a-method-reference-to-an-instance-method-of-an-arbitrary-object-of-a-p
https://stackoverflow.com/questions/25512532/instance-method-reference-and-lambda-parameters
https://segmentfault.com/a/1190000012269548
https://blog.csdn.net/qwe125698420/article/details/53415746
https://blog.csdn.net/learningcoding/article/details/72539918
https://blog.idrsolutions.com/2015/02/java-8-method-references-explained-5-minutes/

原文地址:https://blog.csdn.net/weixin_41126303/article/details/81187002

  • 25
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值