【有书共读】Java攻略 读书笔记01
一、Lambda表达式简介
“Lambda 表达式”(lambda expression)是一个匿名函数,即没有函数名的函数;Lambda表达式不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。
Java Lambda表达式的一个重要用法是简化某些匿名内部类(Anonymous Classes)的写法。
二、Lambda基础语法
基本语法:(parameters) -> expression或(parameters) ->{ statements; }
下面是一些Java lambda表达式的简单例子:
() -> 1 // 1. 不需要参数,返回值为 1 x -> 3 * x // 2. 接收一个参数(数字类型),返回其3倍的值 (x, y) -> x + y // 3. 接受2个参数,并返回x+y (int x, int y) -> x + y // 4. 接收2个int型整数,返回两值的和 (String s) -> System.out.print(s) // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
三、lambda取代某些匿名内部类
下面介绍如何使用Lambda表达式简化匿名内部类的书写,但Lambda表达式并不能取代所有的匿名内部类,只能用来取代函数式接口(Functional Interface)的简写。
函数式接口是一种包含单一抽象方法(single abstract method)的接口。类通过为接口中的所有方法提供实现来实现任何接口,这可以通过顶级类、内部类甚至匿名内部类完成。
3.1 无参函数的简写
·例子1-1 Runnable接口的匿名内部类实现
public class RunnableDemo{
public static void main(String[] args) {
new Thread(new Runnable(){// 接口名
public void run(){// 方法名
System.out.println("run test()");
}
}).start();
//以上代码给Tread类传递了一个匿名的Runnable对象
//重载Runnable接口的run()方法来实现相应逻辑
}
} 例子1-2 使用lambda表达式改写以上代码
public class RunnableDemo{
public static void main(String[] args) {
new Thread(() -> System.out.println("run test()")).start();
// 省略接口名和方法名
}
} 在本例中,由于println方法返回的是void,所以对应的表达式同样会返回void,与run方法的类型相匹配
lambda表达式必须匹配接口中单一抽象方法签名的参数类型和返回类型,这被称为与方法签名兼容。所以,lambda表达式属于接口方法的实现,可以将其赋给该接口类型的引用。
比如上述例子,若要将lambda赋给函数式接口引用可以通过以下例子1-3实现:
Runnable runnable =() -> System.out.println("run test()");
new Thread(runnable).start(); 3.2 有参函数的简写
例子1-4 FilenameFilter的匿名内部类实现
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
public class FilenameFilterDemo {
public static void main(String[] args) {
File directory = new File("src/test/resources");
String[] names = directory.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".txt");
}
});
System.out.println(Arrays.asList(names));
}
}
例1-5 采用lambda表达式改写以上代码
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
public class FilenameFilterDemo {
public static void main(String[] args) {
File directory = new File("src/test/resources");
String[] names = directory.list((dir,name)-> name.endsWith(".txt"));
System.out.println(Arrays.asList(names));
}
} 可以看到,代码要简单的多。参数包含在小括号中,但并未声明类型。在编译时,编译器发现list方法传入一个FilenameFilter类型的参数,从而获知其单一抽象方法accept的签名,进而了解accept的参数为File和String,因此兼容的lambda表达式参数必须匹配这些类型。由于accept方法返回的类型是布尔值,所以箭头右边的表达式也必须是返回布尔值。
我们也可以在代码中指定数据类型,如下例1-6所示:
File directory = new File("src/test/resources");
String[] names = directory.list((File dir,String name)-> name.endsWith(".txt")); 此外,如果lambda表示的实现多于一行,则需要使用大括号和显示返回语句,如例1-7所示:
File directory = new File("src/test/resources");
String[] names = directory.list((File dir,String name)-> {
return name.endsWith(".txt");
}
); 这就是lambda代码块,在本例中,虽然代码主体只有一行,但是可以使用大括号将多个语句括起来。注意,不能省略return关键字。
lambda表达式在任何情况下都不能脱离上下文存在,上下文指定了将表达式赋予给哪个函数式接口。lambda表达式既可以是方法的参数,也可以是方法的返回函数,还可以被赋给引用。无论哪种情况,赋值类型必须为函数式接口。
#笔记##Java##读书笔记#
查看16道真题和解析