Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 494|回复: 0

[Java基础知识]初探Java 8新特性:lambda表达式

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-9-30 17:43:20 | 显示全部楼层 |阅读模式
    Java8带有Lambda表达式的预览版的JDK已经放出来了(地址在最下面),新特性有以下四个:  1.Lambda表达式(或称之为“闭包”或者“匿名函数”)  2.扩展的目标类型  3.方法和构造器引用  4.接口默认方法    本文先介绍一下很值得期待的Lambda表达式,lambda表达式,等同于大多说动态语言中常见的闭包、匿名函数的概念。其实这个概念并不是多么新鲜的技术,在C语言中的概念类似于一个函数指针,这个指针可以作为一个参数传递到另外一个函数中。  
      
       
       

         
       

         
       
      



             由于java是相对较为面向对象的语言,一个Java对象中可以包含属性和方法(函数),方法(函数)不能孤立于对象单独存在。这样就产生了一个问题,有时候需要把一个方法(函数)作为参数传到另外一个方法中的时候(比如回调功能),就需要创建一个包含这个方法的接口,传递的时候传递这个接口的实现类,一般是用匿名内部类的方式来。如下面代码,首先创建一个Runnable的接口,在构造Thread时,创建一个Runnable的匿名内部类作为参数:
      
       
       
        Java代码  
       
       
       
       new Thread(new Runnable() {   
           public void run() {   
                   System.out.println("hello");   
               }   
       }).start();   
       
      
       类似这种情况的还有swing中button等控件的监听器,如下面代码所示,创建该接口的一个匿名内部类实例作为参数传递到button的addActionListener方法中。
      
       
       
        Java代码  
       
       
       
       public interface ActionListener {   
           void actionPerformed(ActionEvent e);   
       }   
          
       button.addActionListener(new ActionListener() {   
         public void actionPerformed(ActionEvent e) {   
           ui.dazzle(e.getModifiers());   
         }   
       });   
       
      
              这样的代码的缺点是有代码笨重,可读性差,不能引用外面的非final的变量等。lambda表达式就是为了解决这类问题而诞生的。
          在介绍Java8中的Lambda表达式之前,首先介绍一个概念叫“函数式接口”(functional interfaces)。对于任意一个Java接口,如果接口中只定义了唯一一个方法,那么这个接口就称之为“函数式接口”。比如JDK中的ActionListener、Runnable、Comparator等接口。
          先来看一下Java8中的lambda表达式的使用示例:
          创建一个线程:
      
       
       
        Java代码  
       
       
       
       new Thread(() -> {System.out.println("hello");}).start();      
       
      
          可以看到这段代码比上面创建线程的代码精简了很多,也有很好的可读性。
          () -> {System.out.println("hello");}  就是传说中的lambda表达式,等同于上面的new Runnable(), lambda大体分为3部分:
          1.最前面的部分是一对括号,里面是参数,这里无参数,就是一对空括号
          2.中间的是 -> ,用来分割参数和body部分
          3.是body部分,可以是一个表达式或者一个语句块。如果是一个表达式,表达式的值会被作为返回值返回;如果是语句块,需要用return语句指定返回值。如下面这个lambda表达式接受一个整形的参数a,返回a的平方
      
       
       
        Java代码  
       
       
       
       (int a) -> a^2     
       
      
         等同于
      
       
       
        Java代码  
       
       
       
       (int a) -> {return a^2;}   
       
      
        继续看更多的例子:
      
       
       
        Java代码  
       
       
       
       (int x, int y) -> x + y   
          
       () -> 42   
          
       (String s) -> { System.out.println(s); }   
       
      
       创建一个FileFilter,文件过滤器:
      
       
       
        Java代码  
       
       
       
       FileFilter java = (File f) -> f.getName().endsWith(".java")   
       
      
       创建一个线程:
      
       
       
        Java代码  
       
       
       
       new Thread(() -> {   
         //do sth here...   
       }).start()   
       
      
       创建一个Callable:
      
       
       
        Java代码  
       
       
       
       Callable<String> c = () -> "done";   
       
      
       创建一个String的比较器:
      
       
       
        Java代码  
       
       
       
       Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2);   
       
      
       而且lambda表达式可以赋值给一个变量:
      
       
       
        Java代码  
       
       
       
       Comparator<String> c;   
       c = (String s1, String s2) -> s1.compareToIgnoreCase(s2);   
       
      
       还可以作为方法的返回值:
      
       
       
        Java代码  
       
       
       
       public Runnable toDoLater() {   
         return () -> {   
           System.out.println("later");   
         };   
       }   
       
      
           从上面可以看到,一个lambda表达式被作为一个接口类型对待,具体对应哪个接口,编译器会根据上下文环境推断出来,如下面的lambda表达式就表示一个ActionListener.
      
       
       
        Java代码  
       
       
       
       ActionListener l = (ActionEvent e) -> ui.dazzle(e.getModifiers());   
       
      
          这有可能会造成一个表达式在不同的上下文中被作为不同的类型,如下面的这种情况,尽管两个表达式是相同的,上面的表达式被推断为Callable的类型,下面的会被推断为PrivilegedAction类型。
      
       
       
        Java代码  
       
       
       
       Callable<String> c = () -> "done";   
       PrivilegedAction<String> a = () -> "done";   
       
      
          那么编译器是根据哪些因为决定一个表达式的类型呢?
          如果一个表达式被推断为是T类型的,需要满足以下4个条件:
          1.T是函数式接口类型(只声明唯一一个方法)
          2.表达式和T中声明的方法的参数个数一致,参数类型也一致
          3.表达式和T中声明的方法的返回值类型一致
          4.表达式和T中声明的方法抛出的异常一致
          有了这个准则,上面的疑问就迎刃而解了
          参考:
          1.State of the Lambda
          2.Java8带有Lambda表达式版本的JDK下载地址
            3.原文发表在 IT译文网:初探Java8新特性之lambda表达式



      
      
       
       

         
       

         
       
      
    复制代码
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-18 08:33 , Processed in 0.391335 second(s), 54 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表