文档章节

Java 8新特性探究(一)通往lambda之路_语法篇

OSC闲人
 OSC闲人
发布于 2013/11/08 14:03
字数 1388
阅读 21101
收藏 199

      现在开始要灌输一些概念性的东西了,这能帮助你理解lambda更加透彻一点,如果你之前听说过,也可当是温习,所谓温故而知新......

      在开始之前,可以同步下载jdk 8 和  IDE,IDE根据个人习惯了,不过eclipse官方版本还没出来,所以目前看的话,netbean7.4是首选的,毕竟前段子刚刚出的正式版本,以下是他们的下载地址。

函数式接口

函数式接口(functional interface 也叫功能性接口,其实是同一个东西)。简单来说,函数式接口是只包含一个方法的接口。比如Java标准库中的java.lang.Runnable和java.util.Comparator都是典型的函数式接口。java 8提供 @FunctionalInterface作为注解,这个注解是非必须的,只要接口符合函数式接口的标准(即只包含一个方法的接口),虚拟机会自动判断,但 最好在接口上使用注解@FunctionalInterface进行声明,以免团队的其他人员错误地往接口中添加新的方法。
Java中的lambda无法单独出现,它需要一个函数式接口来盛放,lambda表达式方法体其实就是函数接口的实现,下面讲到语法会讲到

Lambda语法

包含三个部分

  1. 一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数

  2. 一个箭头符号:->

  3. 方法体,可以是表达式和代码块,方法体函数式接口里面方法的实现,如果是代码块,则必须用{}来包裹起来,且需要一个return 返回值,但有个例外,若函数式接口里面方法返回值是void,则无需{}

总体看起来像这样

(parameters) -> expression 或者 (parameters) -> { statements; }

看一个完整的例子,方便理解

/**
 * 测试lambda表达式
 *
 * @author benhail
 */
public class TestLambda {

    public static void runThreadUseLambda() {
        //Runnable是一个函数接口,只包含了有个无参数的,返回void的run方法;
        //所以lambda表达式左边没有参数,右边也没有return,只是单纯的打印一句话
        new Thread(() ->System.out.println("lambda实现的线程")).start(); 
    }

    public static void runThreadUseInnerClass() {
        //这种方式就不多讲了,以前旧版本比较常见的做法
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("内部类实现的线程");
            }
        }).start();
    }

    public static void main(String[] args) {
        TestLambda.runThreadUseLambda();
        TestLambda.runThreadUseInnerClass();
    }
}

可以看出,使用lambda表达式设计的代码会更加简洁,而且还可读。

方法引用

其实是lambda表达式的一个简化写法,所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是"::",右边是相应的方法名。如下所示:

ObjectReference::methodName

一般方法的引用格式是

  1. 如果是静态方法,则是ClassName::methodName。如 Object ::equals

  2. 如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;

  3. 构造函数.则是ClassName::new

再来看一个完整的例子,方便理解

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;

/**
 *
 * @author benhail
 */
public class TestMethodReference {

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        frame.setLayout(new FlowLayout());
        frame.setVisible(true);
		
        JButton button1 = new JButton("点我!");
        JButton button2 = new JButton("也点我!");
		
        frame.getContentPane().add(button1);
        frame.getContentPane().add(button2);
        //这里addActionListener方法的参数是ActionListener,是一个函数式接口
        //使用lambda表达式方式
        button1.addActionListener(e -> { System.out.println("这里是Lambda实现方式"); });
        //使用方法引用方式
        button2.addActionListener(TestMethodReference::doSomething);
        
    }
    /**
     * 这里是函数式接口ActionListener的实现方法
     * @param e 
     */
    public static void doSomething(ActionEvent e) {
		
        System.out.println("这里是方法引用实现方式");
        
    }
}

可以看出,doSomething方法就是lambda表达式的实现,这样的好处就是,如果你觉得lambda的方法体会很长,影响代码可读性,方法引用就是个解决办法

总结

以上就是lambda表达式语法的全部内容了,相信大家对lambda表达式都有一定的理解了,但只是代码简洁了这个好处的话,并不能打动很多观众,java 8也不会这么令人期待,其实java 8引入lambda迫切需求是因为lambda 表达式能简化集合上数据的多线程或者多核的处理,提供更快的集合处理速度 ,这个后续会讲到,关于JEP126的这一特性,将分3部分,之所以分开,是因为这一特性可写的东西太多了,这部分让读者熟悉lambda表达式以及方法引用的语法和概念,第二部分则是虚拟扩展方法(default method)的内容,最后一部分则是大数据集合的处理,解开lambda表达式的最强作用的神秘面纱。敬请期待。。。。

如果你有建议或者疑问,欢迎在评论里面留言

© 著作权归作者所有

共有 人打赏支持
OSC闲人

OSC闲人

粉丝 3616
博文 22
码字总数 26172
作品 1
深圳
技术主管
私信 提问
加载中

评论(52)

管龙
管龙
被讨论是好事,我的水平这是一篇非常非常好的文章,虽然看的有点晚!
开源X
开源X
很不错,唉现在才开始看
JerryLin
JerryLin

引用来自“JerryLin”的评论

请教一下:

1。
e -> { System.out.println("这里是Lambda实现方式"); }

这个式子怎么才能在别的地方引用?

2。
public static void doSomething(ActionEvent e) {

System.out.println("这里是方法引用实现方式");
  
}

这个形式怎么和普通的静态函数区分?

引用来自“成熟的毛毛虫”的评论

1.首先要理解函数式接口,它是盛放lambda表达式的地方,换句话说,任何有函数式接口的地方都可以用lambda表达式,比如Thread t1=new Thread(() ->System.out.println("lambda实现的线程")); 2.他就是普通的静态函数
了解,thanks
OSC闲人
OSC闲人

引用来自“JerryLin”的评论

请教一下:

1。
e -> { System.out.println("这里是Lambda实现方式"); }

这个式子怎么才能在别的地方引用?

2。
public static void doSomething(ActionEvent e) {

System.out.println("这里是方法引用实现方式");
  
}

这个形式怎么和普通的静态函数区分?
1.首先要理解函数式接口,它是盛放lambda表达式的地方,换句话说,任何有函数式接口的地方都可以用lambda表达式,比如Thread t1=new Thread(() ->System.out.println("lambda实现的线程")); 2.他就是普通的静态函数
JerryLin
JerryLin
请教一下:

1。
e -> { System.out.println("这里是Lambda实现方式"); }

这个式子怎么才能在别的地方引用?

2。
public static void doSomething(ActionEvent e) {

System.out.println("这里是方法引用实现方式");
  
}

这个形式怎么和普通的静态函数区分?
南北024
南北024
怎么感觉不像是java了呢?
幻の上帝
幻の上帝

引用来自“长工”的评论

引用来自“成熟的毛毛虫”的评论

引用来自“Linux_Ultimate”的评论

有意义吗?Java还是老实一点吧

有很大意义,坐吃山空的道理相信大家都懂,如果死抱着之前的优势慢慢就会没落,况且java现在除了庞大的开源生态环境,几乎没什么优势了,闭包特性是几乎所有主流的面向对象编程语言都支持,java坚持了很久也很傻,所以现在lambda是java的一个进步。至少我看来是。。。

lambda从来就和”面向对象“毫无关系,早在十多年,面向对象技术已经被玩的滚瓜烂熟了。lambda是近几年才搞出的新东西,不知道有什么用。Java里的东很多了,java se成千上万个类,api,javaee又多了一堆,再多个lambda也无所谓,即使它没什么用处。

扯吧。Java的方法还不是抄C艹的成员函数,C艹的无非抄C和Simula的,C的函数因为当初发明者对高级语言理论的了解和设计经验的不足以及实现上的偷懒所以才搞成了半吊子——实际上就是lambda abstraction的阉割劣化版。懂了么。

肖羊
闭包在javascript中就有点看不懂了,完全不能了解有什么很大的作用
这个文章也没有看懂,唉、多看几遍好了
黄四洲
其实java web开发人员早就可以接触到lambda(lamada)表达式。jave ee7 规范。el表达式3.0,早就有关于兰姆达表达式的完整支持。虽说不是jdk本身支持但jsp毕竟也只支持ava语言现在。所以说lambda这个东西java是必须有但是火不起来至少10年内火不起来预测。企业是很不待见新的东西。连java ee7能不能在10年内普及都是问题。
北极的晓风
北极的晓风
学习了!
Java 8新特性探究(二)深入解析默认方法

上篇讲了 lambda表达式的语法,但只是 JEP126 特性的一部分,另一部分就是默认方法(也称为虚拟扩展方法或防护方法) 什么是默认方法,为什么要有默认方法 简单说,就是接口可以有实现方法,...

OSC闲人
2013/11/13
0
49
Java 8新特性探究(三)解开lambda最强作用的神秘面纱

我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值。现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析...

OSC闲人
2013/11/18
0
42
Java 8 新特性,Lambda,方法引用,Stream,Optional

在C++、Python等语言里都有Lambda表达式,Java 8也新增了这一特性。 在java给变量赋值是这样的: 如果你想把“一块代码”赋给一个Java变量,应该怎么做呢? 比如,我想把右边那块代码,赋给一...

saulc
07/10
0
0
Java 8会干掉Scala吗?

2014-04-15 孙镜涛 InfoQ 最令人期待的Java 8已于2014年3月18日发布,该版本包含很多令人兴奋的新特性,被认为是自Java 5发布以来对Java做出的最大改变。对于开发者而言,最值得注意的特性包...

Yamazaki
2014/04/23
0
0
在 Java 8 中避免 Null 检查

如何预防 Java 中著名的 NullPointerException 异常?这是每个 Java 初学者迟早会问到的关键问题之一。而且中级和高级程序员也在时时刻刻规避这个错误。其是迄今为止 Java 以及很多其他编程语...

ApacheCN飞龙
2016/02/04
8.1K
24

没有更多内容

加载失败,请刷新页面

加载更多

RestClientUtil和ConfigRestClientUtil区别说明

RestClientUtil directly executes the DSL defined in the code. ConfigRestClientUtil gets the DSL defined in the configuration file by the DSL name and executes it. RestClientUtil......

bboss
今天
11
0

中国龙-扬科
昨天
2
0
Linux系统设置全局的默认网络代理

更改全局配置文件/etc/profile all_proxy="all_proxy=socks://rahowviahva.ml:80/"ftp_proxy="ftp_proxy=http://rahowviahva.ml:80/"http_proxy="http_proxy=http://rahowviahva.ml:80/"......

临江仙卜算子
昨天
9
0
java框架学习日志-6(bean作用域和自动装配)

本章补充bean的作用域和自动装配 bean作用域 之前提到可以用scope来设置单例模式 <bean id="type" class="cn.dota2.tpye.Type" scope="singleton"></bean> 除此之外还有几种用法 singleton:......

白话
昨天
8
0
在PC上测试移动端网站和模拟手机浏览器的5大方法

总结很全面,保存下来以备不时之需。原文地址:https://www.cnblogs.com/coolfeng/p/4708942.html

kitty1116
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部