Lambda,是不是听着很熟悉,没错,在高等数学中这货经常和我们打交道,哈哈,这是一个希腊字母了,排名第十一,大写是Λ,小写是λ。
好了,是这样的。jdk1.8中新增的核心特性有lambda表达式,函数式接口,流API,默认方法,新的Date,以及Time API。
下面给大家介绍的是Lambda表达式,该表达式允许我们把行为传到函数里。之前把行为传到函数里我们采用的是匿名内部类,该方法导致行为最重要的方法夹杂在中间,不够突出。
lambda表达式取代了匿名内部类,取消了模板,允许程序猿用函数式风格编写代码,使代码可读性更高,尽管刚开始你会看不懂,但是你应该尝试,毕竟这是新的东西,我已从中获益。
Lambda表达式是在JDK 8中开始支持的一种函数式推导语言, 能够大量减少匿名内部类那种冗余的代码。 在Android中, 可以大量使用在设置监听, 设置异步回调等场景。
基本格式是:() -> {}
有下面三种具体表达:
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 module 的build.gradle
apply 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() {
@Override
public 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);
} p
ublic 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 box = new ArrayList();
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());
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"));