zoukankan      html  css  js  c++  java
  • (转)JDK 1.8 预览版Lambda语法分析

    一、lambda含义
        lambda表示数学符号“λ”,计算机领域中λ代表“λ演算”,表达了计算机中最基本的概念:“调用”和“置换”。在很多动态语言和C#中都有相应的lambda语法,这类语法都为了简化代码,提高运行效率。

    二、lambda 项目的背景,参考这里。
        无论是面向对象语言还是函数式语言,基本数值都可以被动态的封装入程序动作:面向对象语言通过“方法”,函数式语言通过“函数。
        介于“方法”和“函数”的定义有很多种,补充下IBM知识库的解释:
    在面向对象语言中,方法不是一阶值(First-class value),在函数式语言中,函数是一阶值。在函数式语言中,函数可以作为另一个函数的返回值或参数,还可以作为一个变量的值,函数可以嵌套定义,而在面向对象语言中的的“方法”做不到这点。
        Java可以说是面向对象语言的代表,如果要调用其方法,需要先创建对象。不过Java对象都是“重量级”的,实例化具体的类的对象,需要经过定义和申明 两个阶段。比如定义方法,并给内部字段赋初始值。但是一个对象只包含一个方法的情况很多,比如实现API中的“回调接口”功能的类,在swing中有接 口:

    Java代码 
    public interface ActionListener {  
        void actionPerformed(ActionEvent e); 


       现有的实现方式大多是:

    Java代码 
    button.addActionListener(new ActionListener() {  
      public void actionPerformed(ActionEvent e) {  
        ui.dazzle(e.getModifiers()); 
      } 
    }); 

        很多现有的类库都基于这种设计实现,所以对于代码被明确定义运行在单独线程的API来说,匿名内部类尤为重要。这些匿名内部类只存在于创建它的线程中。但 是在并行计算领域,CPU的制造商着力发展多核技术来提升CPU的功能,这么做几乎无法依靠多核的优势来提升其性能。


        鉴于回调函数和其他功能式语法的关系越来越密切,所以必须建立尽可能的轻量级的数据模型(从编码角度而言,性能方面下文再说)。对于这点来说匿名内部类的缺点如下:
    1. 语法相对复杂。
    2. 在调用内部类的上下文中,指引和this的指代容易混淆。
    3. 类加载和实例创建语法不可避免。
    4. 不能引用外部的非final对象。
    5. 不能抽象化控制流程


        针对这些问题,lambda项目致力于
    1. 消除问题1和问题2,通过引入更简单的表达式和局部变量的定义规则。
    2. 回避问题3,定义更灵活更友善的语法。这里只是回避,类加载和实例化本身不可避免。下文会解释。
    3. 改善问题4,允许用户使用最终有效的局部变量。

        不过lambda项目目前并不能解决所有关于内部类的问题。问题4和问题5没有完全解决,这计划在将类版本中继续改善。对于性能方面,原文也没有提,不过后面有些补充。


    三、lambda用法
        通过上文可以了解到,lambda语法是针对“回调接口”和“匿名内部类”作出的改进,所以lambda的语法目前仅对于部分接口,这些接口的特点是只含 一个抽象方法,在lambda项目中,早期称为SAM类型(SAM = single abstract method 即单一抽象方法)。在最新的文档中(即这个版本),它们有了新名字,叫函数接口(functional interface),比如:

    1 java.lang.Runnable
    2 java.util.concurrent.Callable
    3 java.security.PrivilegedAction
    4 java.util.Comparator
    5 java.io.FileFilter
    6 java.nio.file.PathMatcher
    7 java.lang.reflect.InvocationHandler
    8 java.beans.PropertyChangeListener
    9 java.awt.event.ActionListener
    10 javax.swing.event.ChangeListener

    lambda的语法包括三部分
    1、参数列表
    2、箭头符号"->"
    3、代码块。


        其中代码块很像一个方法体,return语句将控制权交还给匿名方法(anonymous method,即lambda表达式)的调用者;break和continue不能出现在函数体的顶部,不过可以出现在内部的循环里;如果代码块得出最终 结果,那么每一个控制路径(control path) 必须都有返回或抛出异常。
    如果代码块只有简单一行,可以省略return关键字和“{}”符号(以下所写的例子都是基于JDK 1.8 lambda预览版),比如:


    Java代码 
    public class LambdaTest {    
        public static void main(String... args) { 
            //这里有{}和return 以及 ; 
            Runnable r = () -> { System.out.println("hello world"); }; 
             
            //这里不需要{}和return 
            java.util.Comparator<String> c = (String s1, String s2) -> s2.length()-s1.length();         
            r.run(); 
            System.out.println(c.compare("s1", "12323")); 
        } 



    输出为:
    hello world
    3


    除了这些现有接口,我们还可以自定义函数接口:

    Java代码 
    public class LambdaTest { 
        interface lambdaInterface { 
            public void me(String str); 
        } 
     
        public static void main(String... args) { 
            lambdaInterface li = (String s)->{System.out.println(s);}; 
            li.me("hello world!"); 
        } 

    输出为:

    hello world!

        新的lambda方法从语法上的确是简化了很多。和lambda第一次发布的语法相比也优雅很多。

  • 相关阅读:
    使用 adb 调用 ActivityManager
    shell编程学习
    ActivityInstrumentationTestCase2 和 ActivityUnitTestCase
    安装python的selenium webdriver库
    Ruby selenium-webdriver 测试笔记(一)
    android自动化框架简要剖析(一):运行原理+基本框架
    android自动化框架简要剖析(二):Instrumentation+junit.framework.TestCase
    adb使用手册
    最近常用到的adb命令
    adb无法启动,处理方式:卸载360手机助手
  • 原文地址:https://www.cnblogs.com/backpacker/p/3261484.html
Copyright © 2011-2022 走看看