JDK8新特性—Lambda简洁代码以及其他

来源:互联网 发布:淘宝图片怎么搜索引擎 编辑:程序博客网 时间:2024/06/16 13:02

这里写图片描述

介绍

Lambda,是不是听着很熟悉,没错,在高等数学中这货经常和我们打交道,哈哈,这是一个希腊字母了,排名第十一,大写是Λ,小写是λ。

好了,是这样的。jdk1.8中新增的核心特性有lambda表达式,函数式接口,流API,默认方法,新的Date,以及Time API。

下面给大家介绍的是Lambda表达式,该表达式允许我们把行为传到函数里。之前把行为传到函数里我们采用的是匿名内部类,该方法导致行为最重要的方法夹杂在中间,不够突出。

lambda表达式取代了匿名内部类,取消了模板,允许程序猿用函数式风格编写代码,使代码可读性更高,尽管刚开始你会看不懂,但是你应该尝试,毕竟这是新的东西,我已从中获益。

优点

Lambda表达式是在JDK 8中开始支持的一种函数式推导语言, 能够大量减少匿名内部类那种冗余的代码。 在Android中, 可以大量使用在设置监听, 设置异步回调等场景。

格式

基本格式是:() -> {}

有下面三种具体表达:

  1. (params) -> expression
  2. (params) -> statement
  3. (params) -> {statement}

lambda使用举例

1.引入retrolambda插件:

as里的配置
要使用lambda,首先必须配置编译环境,这里使用的android studio,as默认的jdk版本是1.6,修改成1.8即可使用,这里确保你系统安装了jdk1.8,否则需要用到下面插件: gradle-retrolambda

一。 jdk8裝上二。在project 的build.gradle dependencies {        classpath 'com.android.tools.build:gradle:2.0.0'        classpath 'me.tatarka:gradle-retrolambda:3.2.5'    }三。在android modulebuild.gradleapply plugin: 'com.android.application'apply plugin: 'me.tatarka.retrolambda'android {    //设置当前的jdk编译版本 8    compileOptions {        sourceCompatibility JavaVersion.VERSION_1_8        targetCompatibility JavaVersion.VERSION_1_8    }

设置项目结构
按快捷键Ctrl+Shift+Alt+S进入项目结构设置,把app的jdk版本修改成1.8,注意你需要填写1.8,因为那个下拉菜单里没有这一选项,如下:
这里写图片描述
这里采用的是第二种方法,然后项目自动同步。

同步后是会在build.gradle脚本下生成和上面一样的东东:
这里写图片描述

举例

点击按钮触发事件
传统的点击事件,应用匿名内部类:

Button button = (Button) findViewById(R.id.btn_insert);    button.setOnClickListener(new View.OnClickListener() {        @Override        public void onClick(View v) {            Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_LONG).show();        }    });

通过上面设置jdk版本为1.8后,鼠标放到new View.OnClickListener()里会有下面
然后我们按快捷键Alt+Enter,是这样的

Button button = (Button) findViewById(R.id.btn_insert);button.setOnClickListener(v -> Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_LONG).show());

一行代码就搞定了,清晰可见,把行为传到了函数里,这里注意v不可省略,是函数onClick的参数,当然就可以是任意名字,我还是建议就用一个字母表示,简单嘛,当然了首先你得知道她的意思,尽管她的很多行为你始终不会明白

实现Runnable接口
传统实现Runnable接口是这样的:

new Thread(new Runnable() {    @Override    public void run() {        Log.i("TAG", "haha");    }}).start();

使用lambda表达式之后是这样的:

new Thread(() -> {    Log.i("TAG", "haha");}).start();

这里写图片描述

栗子

private void case2() {//2.2.按钮点击Button button = (Button) findViewById(R.id.btn);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "点", Toast.LENGTH_SHORT).show();}});button.setOnClickListener((View v) ->Toast.makeText(MainActivity.this, "点", Toast.LENGTH_SHORT).show());}

方法引用 ::

1。 方法引用是什么? 是lambda表达式的一个简化写法. 方法引用语法:左边是容器( 可以是类名, 实例名) , 中间是” :: “, 右边是相应的方法名。 如下

一般方法的引用格式是
如果是静态方法, 则是ClassName::methodName。 如 Object ::equals
如果是实例方法, 则是Instance::methodName。 如Object obj=new Object();obj::equals;
构造函数.则是ClassName::new

//这里setOnClickListener方法的参数是OnClickListener, 是一个函数式接口//使用lambda表达式方式button1.setOnClickListener(v -> { System.out.println("这里是Lambda实现方式"); });//使用方法引用方式button2.setOnClickListener(TestMethodReference::doSomething);} public static void doSomething(ActionEvent e) {System.out.println("这里是方法引用实现方式");}
private void case3() {//2.3.双冒号:: 更简化的lambda表达式Button button = (Button) findViewById(R.id.btn);//button.setOnClickListener(Cat::toast);//调用静态方法的例子 要求toast的参数与OnClickListner一致//Cat cat=new Cat();//button.setOnClickListener(cat::toast2);//调用成员方法的例子 要求toast2的参数与OnClickListner一致button.setOnClickListener(Cat::new);//调用构造方法方法的例子 要求构造方法的参数与OnClickListner一致}

比较

既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析。

第一个关键的不同点就是关键字 this。匿名类的 this 关键字指向匿名类,而lambda表达式的 this 关键字指向包围lambda表达式的类。

第二是编译方式。Java编译器将lambda表达式编译成类的私有方法。使用了Java 7的 invokedynamic 字节码指令来动态绑定这个方法。

泛型的目标类型推断

什么是泛型 泛型是Java SE 1.5的新特性, 通俗点将就是“类型的变量”。 这种类型变量可以用在类、 接口和方法的创建中。

List<Apple> box = new ArrayList<Apple>();box.add(new Apple());Apple apple =box.get(0);

如果没有泛型就可需要类型转换

Apple apple = (Apple)box.get(0);

什么是自动推断
java7的泛型类型推断改进:为了减少泛型的代码长度。
例如: Jdk7之前

Map<String, String> myMap = new HashMap<String, String>();

而使用jdk7自动推断之后:

Map<String, String> myMap = new HashMap<>(); //注意后面的"<>"

为什么可以这样做?
声明变量的的时候已经指明了参数类型, 所以就不需要在初始化对象时再指定? 看到这点:JDK7新增了根据声明变量获取参数类型的这一特性就叫 自动推断 .
Java8的泛型类型推断改进

//通过方法赋值的目标参数来自动推断泛型的类型List<String> l = List.nil();//而不是显示的指定类型//List<String> l = List.<String>nil();//通过前面方法参数类型推断泛型的类型List.cons(42, List.nil());//而不是显示的指定类型//List.cons(42, List.<Integer>nil());

forEach

1。 外部VS forEach 内部迭代 以前Java集合是不能够表达内部迭代的, 而只提供了一种外部迭代的方式, 也就是for或者while循环。
jdk8之前

List persons = asList(new Person("Joe"), new Person("Jim"), new Person("John"));for (Person p : persons) {p.setLastName("Doe");}

jdk8 用lambda和Collection.forEach重写上面的循环

persons.forEach(p->p.setLastName("Doe"));
0 0
原创粉丝点击