关于java8的方法引用

关于java8的方法引用

今天偶然看到一段代码

	//首先有一个Studeng类 有一个静态方法,有个实例方法
   class Student{
   		class Student {

    private String name;

    public Student(){
    }
    public Student(String name){
        this.name = name;
    }
	//实例方法 say()
    public  void say() {
        System.out.println(name);
    }
	//静态方法 say2()
    public  static void say2(String name) {
        System.out.println(name);
    }

}

注意:lists2.forEach(Student::say);
Student是类名, say() 是实例方法;
这里就是我的疑问,为什么可以调用实例方法呢?不应该通过对象调用吗??

List<Student> lists2 = Arrays.asList(newStudent("张三"),new Student("李四"));
lists2.forEach(Student::say); 
 //注意 这里Student是类名,调用的是实例方法say(),这里就是我的疑问,为什么可以调用实例方法呢?不应该通过对象调用吗??

lists2.forEach(Student::say); 为啥这里可以调用类的实例方法呢?

于是乎,我又写了一个例子,我把List的泛型里面的类型改成:String,
结果:发现如果在调用say()实例方法就会编译器报错
这里就必须调用静态方法say2()静态方法才行!
那就奇了怪了,为啥一个可以调用,一个编译报错
这里乳沟像上面调用类的实例方法就会报错
改成静态方法就可以了

  List<String> lists = new ArrayList<>();
  lists.forEach(Student::say2); 
  //这里就必须调用静态方法了,否则的话编译器会报错!如上图

那这是为什么呢?上面的为什么可以通过类调用实例方法呢?
我们都知道 :类是优先于实例存在的,我们new()一个对象,必须要先加载类!
大家可以看到这两个方法唯一的区别就是list 里面的类型
一个是Student类,一个是String 类,类型不同
所以我就去看了java8的文档,终于解决我的疑问了;
以下摘自java8文档:

引用与Java8文档内容:
如何构建方法引用方法引用主要有三类。
(1) 指向静态方法的方法引用(例如Integer的parseInt方法,写作Integer::parseInt)。
(2) 指向任意类型实例方法的方法引用(例如String的length方法,写作String::length)。
(3) 指向现有对象的实例方法的方法引用(假设你有一个局部变量expensiveTransaction用于存放Transaction类型的对象,它支持实例方法getValue,那么你就可以写expensiveTransaction::getValue)。第二种和第三种方法引用可能乍看起来有点儿晕。类似于String::length的第二种方法引用的思想就是你在引用一个对象的方法,而这个对象本身是Lambda的一个参数。例如,Lambda表达式(String s) -> s.toUppeCase()可以写作String::toUpperCase。但第三种方法引用指的是,你在Lambda中调用一个已经存在的外部对象中的方法。

方法引用的三类

分析:
(1):指向静态方法的方法引用:就是 类名::静态方法

 List<String> lists = new ArrayList<>();
 lists.forEach(Student::say2); 
 //类名:Student::静态方法:say2,这个很好理解

(3) :指向现有对象的实例方法的方法引用:就是 对象::实例方法

List<String> lists = new ArrayList<>();
Student stu = new Student();
lists.forEach(stu::initMethod);
//已存在的外部对象:student的实例方法:initMethod
//这个也很好理解,就是调用对象的方法 对象::实例方法

上面两个都是很好理解的,跟我们理解的一样,类调用静态方法,对象调用实例方法,第二种就是上面遇到的情况

(2) :****☆指向任意类型实例方法的方法引用:
你在引用一个对象的方法,而这个对象本身是Lambda的一个参数。例如,Lambda表达式(String s) -> s.toUppeCase()可以写作String::toUpperCase。因为String类型是lambda的一个参数
但第三种方法引用指的是,你在Lambda中调用一个已经存在的外部对象中的方法。

List<Student> lists2 = Arrays.asList(newStudent("张三"),new Student("李四"));
lists2.forEach(Student::say); 
**//所以这里我们就应该明白为什么可以调用实例方法了,
因为我们的Student类型是lambda的一个参数,
所以才可以调用Student的实例方法**

补充一个例子,害怕大家没有理解

 List<String> lists = new ArrayList<>();
 lists.forEach(String::length);
 //String的length方法并不是静态方法,为什么可以调用,是因为String类型是lambda的一个参数,所以可以调用

String的length方法并不是一个静态方法,为什么可以类名:: zh这样的形式调用,主要是 因为String是lambda的一个参数,所以可以调用String的实例方法

总结

因为我们的Student对象是lambda的一个参数,所以才可以调用实例方法,文档也解决了我的疑惑!欢迎大家一起交流

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值