1.Java8之前匿名内部类例子
//1.Java8之前Swing程序Jbutton注册时间监听器
JButton jButton = new JButton();
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
}
});
2.Java8使用Lambda表达式
//2.Java8使用Lambda表达式注册事件监听器
jButton.addActionListener(event -> System.out.println("button clicked"));
总结:使用Lambda表达式后,可以发现代码行数从6行变成1行,原因是Lambda表达式无需将ActionListener对象传入,只需传入行为,这样代码大幅度简化。
3.Lambda其他表现形式
//3.Lambda表达式其他表现形式
//无参数Lambda表达式
Runnable noArgument = () -> System.out.println("no args");
//代码块Lambda
Runnable multiStatements = () -> {
System.out.print("multi");
System.out.println("Statuments");
};
//多参数Lambda
BinaryOperator<Long> add = (x, y) -> x + y;
//多参数也可以声明类型
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
目标类型:Lambda表达式所在上下文环境的类型。比如,将Lambda表达式赋值给一个局部变量,或传递给一个方法作为参数,局部变量或方法参数的类型就是Lambda表达式的目标类型。
4.局部变量引用
//4.局部变量引用(错误用法)
String str = "abc";
str = "def";
Runnable helloWorld = () -> {
System.out.println(str);
};
//正确用法
String str2 = "abc";
Runnable helloWorld = () -> {
System.out.println(str2);
};
如上代码编译器会报错,因为匿名内部类只能引用final变量或既成事实上的final变量,换句话说,Lambda引用的是变量的值,而不是变量本身,这种行为也解释了为什么Lambda表达式被称为闭包。未赋值的变量(str2)与周边环境(即匿名内部类外部)隔离起来,进而被绑定到一个特定的值("abc")。
5.函数接口
函数接口是只有一个抽象方法的接口,用作Lambda表达式的类型。以下是Java8提供的常用函数接口。
/*
*predicate<T> 返回值boolean
* 判断传入参数是否大于10
*/
Predicate<Integer> predicate = x -> x > 10;
System.out.println(predicate.test(12));
/*
*Consumer<T> 返回值void
*输出一个值
*/
Consumer<String> consumer = x -> System.out.println(x);
consumer.accept("name");
/*
*Function<T, R> 返回值R
*将整型转换为字符串类型
*/
Function<Integer, String> integerToString = x -> String.valueOf(x);
System.out.println(integerToString.apply(new Integer(10)));
/*
*Supplier<T> 返回值T
*返回当前时间字符串形式
*/
Supplier<String> getTime = () -> {
Date now = new Date();
return now.toString();
};
System.out.println(getTime.get());
/*
*UnaryOperator<T> 返回值T
*逻辑非
*/
UnaryOperator<Boolean> not = x -> !x;
System.out.println(not.apply(Boolean.TRUE));
/*
*BinaryOperator<T> 返回值T
*求两个数的乘积
*/
BinaryOperator<Long> multiple = (x, y) -> x * y;
System.out.println(multiple.apply(4L, 4L));
6.类型推断(javac根据上下文信息就能推断出参数的正确类型,程序依然要通过类型检查来保证运行的安全性,但不用再显示声明类型)
public class Test {
public static void main(String[] args){
Test test = new Test();
test.useHashMap(new HashMap<>());
}
public void useHashMap(Map<String, String> values){
System.out.print("");
}
}
如果将构造函数直接传递给一个方法,也可以根据方法签名来推断类型,以上useHashMap方法可以自动推断出泛型的类型。