Java8的新特性有哪些
新特性的特征:
速度更快
代码更少(增加了新的语法:Lambda 表达式)
强大的 Stream API
便于并行
最大化减少空指针异常:Optional
Nashorn引擎,允许在JVM上运行JS应用
lambda表达式
什么是lambda表达式?
Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以
传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了
提升
为什么要有lambda表达式?
Lambda表达式。它可以让你很简洁地表示一个行为或传递代码。现在你可以把Lambda 表达式看作匿名功能,它基本上就是没有声明名称的方法,但和匿名类一样,它也可以作为参 数传递给一个方法。
哪些场景可以使用到lambda表达式?
?????
首先我们看下再没有使用lambda的时候使用匿名内部类的对比
lambda与匿名内部类对比
//匿名内部类
Comparator c1 = new Comparator() {
@Overridepublic intcompare(Integer t1, Integer t2) {returnInteger.compare(t1,t2);
}
};int compareNumOne = c1.compare(12,13);
System.out.println(compareNumOne);//-1
System.out.println("==========Lambda==========");//lambda表达式
Comparator c2 = (c3,c4) ->Integer.compare(c3,c4);int compareNumTwo = c2.compare(11,10);
System.out.println(compareNumTwo);//1
可以看出lambda表达式简洁了很多,直接了,不像以前这么难懂 还有一大堆的内部逻辑
匿名内部类
Button button = new Button("Send");
button.setOnAction(new EventHandler() {
public void handle(ActionEvent event) {
label.setText("Sent!!");
}
});
这里,setOnAction方法的行为就用EventHandler参数化了。用Lambda表达式的话,看 起来就是这样:
button.setOnAction((ActionEvent event) -> label.setText("Sent!!"));
上面可以看出lambda使用起来很方便的 简单明了
lambda的使用
lambda的结构
参数列表——这里它采用了Comparator中compare方法的参数,两个Apple。
箭头——箭头->把参数列表与Lambda主体分隔开。
Lambda主体——比较两个Apple的重量。表达式就是Lambda的返回值了。
1.举例: (o1,o2) ->Integer.compare(o1,o2);* 2.格式:* ->:lambda操作符 或 箭头操作符* ->左边:lambda形参列表 (其实就是接口中的抽象方法的形参列表)* ->右边:lambda体 (其实就是重写的抽象方法的方法体)
Lambda 表达式:在Java 8 语言中引入的一种新的语法元素和操 作符。这个操作符为 “->” ,该操作符被称为 Lambda 操作符 或箭头操作符。
它将 Lambda 分为两个部分:
左侧:指定了 Lambda 表达式需要的参数列表
右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即 Lambda 表达式要执行的功能。
下面给出了Java 8中五个有效的Lambda表达式的例子
Lambda表达式的使用(分六种)
语法格式一:无参,无返回值
Runnable r1 = () -> {System.out.println("Hello Lambda");};
r1.run();
语法格式二:Lambda需要一个参数,但是没有返回值
Consumer con = (String s) -> {System.out.println(s);};
con.accept("value");
语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
Consumer con = (s) -> {System.out.println(s);};
con.accept("value");
语法格式四:Lambda若只需要一个参数,参数的小括号可以省略
Consumer con = s -> {System.out.println(s);};
con.accept("value");
语法格式五:Lambda需要两个以上的参数,多条执行语句,并且可以有返回值
Consumer con = (x,y) -> {
System.out.println(x);
return x.compareTo(y);
}
语法格式六:当Lambda体只有一条语句时,return与大括号
Comparator com = (o1, o2) -> o1.compareTo(o2);
com.compreTo(10,13);
//语法格式一:无参,无返回值
@Testpublic voidTestPOne(){
Runnable r1= newRunnable() {
@Overridepublic voidrun() {
System.out.println(" I'm one");
}
};
r1.run();
System.out.println("=======lambda======");
Runnable r2= () -> System.out.println("I'm lambda'One");
r2.run();
}//语法格式二:Lambda 需要一个参数,但是没有返回值。
@Testpublic voidTestTwo(){
Consumer con1 = new Consumer() {
@Overridepublic voidaccept(String s) {
System.out.println(s);
}
};
con1.accept("老王");
System.out.println("=======lambda======");
Consumer con2 = (String s1) ->{System.out.println(s1);};
con2.accept("我是lambda老王");
}//语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”//类型推断想我们之前遇到的泛型和数组一样
/*Consumer con = new Consumer<>(); // 省略后面的String类型
int [] len = new int [] {1,2,3}; 可以 写成 int [] len = {1,2,3}*/@Testpublic voidTestThree(){
Consumer con = new Consumer() {
@Overridepublic voidaccept(String s) {
System.out.println(s);
}
};
con.accept("老王头");
System.out.println("=======lambda======");
Consumer con1 = (s) ->{ System.out.println(s); };
con1.accept("吾乃lambda老王头");
}//语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略
@Testpublic voidTestFour(){
Consumer con = new Consumer() {
@Overridepublic voidaccept(String s) {
System.out.println(s);
}
};
con.accept("老刘");
System.out.println("=======lambda======");
Consumer con1 = s ->{System.out.println(s);};
con1.accept("吾乃lambda老刘");
}//语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
@Testpublic voidTestFive(){
Comparator com = new Comparator() {
@Overridepublic intcompare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);returno1.compareTo(o2);
}
};
System.out.println(com.compare(13, 14));
System.out.println("=======lambda======");
Comparator com1 = (l1,l2) ->{
System.out.println(l1);
System.out.println(l2);returnl1.compareTo(l2);
};
System.out.println(com1.compare(11, 10));
}//语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
@Testpublic voidTestSix(){//原有
Comparator com = (o1, o2) -> {returno1.compareTo(o2);};
System.out.println(com.compare(10, 11));//优化后
Comparator com1 = (l1, l2) ->l1.compareTo(l2);
System.out.println(com1.compare(20, 10));
}
由上可以看出lambda只是修改了 以前写法的方法体 方法后面的执行和参数的传递依旧时不变的 只需要看方法体怎么改变即可。
Summary
* 3. Lambda表达式的使用:(分为6种情况介绍)*
*总结:* ->左边:lambda形参列表的参数类型可以省略(类型推断);如果lambda形参列表只有一个参数,其一对()也可以省略* ->右边:lambda体应该使用一对{}包裹;如果lambda体只有一条执行语句(可能是return语句),省略这一对{}和return关键字*
* 4.Lambda表达式的本质:作为函数式接口的实例*
* 5. 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。我们可以在一个接口上使用 @FunctionalInterface 注解,*这样做可以检查它是否是一个函数式接口。*
* 6. 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。
函数式接口
什么是函数式接口
只包含一个抽象方法的接口,称为函数式接口。
为什么要有函数式接口
Java从诞生日起就是一直倡导“一切皆对象”,在Java里面面向对象(OOP) 编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,
Java不 得不做出调整以便支持更加广泛的技术要求,也即java不但可以支持OOP还 可以支持OOF(面向函数编程)
说白了 函数式接口就是为了让java能面向函数编程而创建的
函数式接口的作用
用函数式接口可以干什么呢?Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例(具体说来,是函数式接口一个具体实现 的实例)
你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式 抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽 象方法上进行声明)。
我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检 查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个 接口是一个函数式接口。
在java.util.function包下定义了Java 8 的丰富的函数式接口
简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是 Lambda表达式和函数式接口的关系。也就是说,
只要一个对象是函数式接口 的实例,那么该对象就可以用Lambda表达式来表示。
所以以前用匿名实现类表 示的现在都可以用Lambda表达式来写。
自定义函数式接口
只需要在自定义的接口上加入@FunctionalInterface 注解即可让这个接口成为函数事接口
@FunctionalInterfacepublic interfaceMyInterface {public voidmethod1();
}
自定义函数接口与Lambda的使用
Java 内置四大核心函数式接口
其它接口
Lambda与函数式接口的使用
//根据传递参数输出信息
public void happyTime(double money, Consumercon){
con.accept(money);
}//根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定
public List filterString(List list, Predicatepre){
List filterList = new ArrayList<>();for(String s:list
) {if(pre.test(s)){ //如果参数s满足定义的Predicate的String泛型
filterList.add(s);
}
}returnfilterList;
}
@Testpublic voidTestMonday(){
happyTime(500, new Consumer() {
@Overridepublic voidaccept(Double aDouble) {
System.out.println("去隔壁洗浴中心消费"+aDouble);
}
});
System.out.println("=====lambda====");
happyTime(4000, money -> System.out.println("买了大宝剑花费"+money));
}
@Testpublic voidTestTuesday(){
List list = Arrays.asList("老王", "老张头","隔壁老王","隔壁小姐姐");
List list1 = filterString(list, new Predicate() {
@Overridepublic booleantest(String s) {return s.contains("老"); //包含老的字符串
}
});
System.out.println(list1);
List list2 = filterString(list,s -> s.contains("老") );
System.out.println(list2);
}
lambda与方法搭配使用必须满足函数式接口的要求,
下面既不是接口种的方法
Practices
1:
(1) 这个Lambda没有参数,并返回void。它类似于主体为空的方法:public voidrun() {}。
(2) 这个Lambda没有参数,并返回String作为表达式。
(3) 这个Lambda没有参数,并返回String(利用显式返回语句)。
(4) return是一个控制流语句。要使此Lambda有效,需要使花括号,如下所示: (Integer i) -> {return "Alan" +i;}。
(5)“Iron Man”是一个表达式,不是一个语句。要使此Lambda有效,你可以去除花括号 和分号,如下所示:(String s) -> "Iron Man"。或者如果你喜欢,可以使用显式返回语 句,如下所示:(String s)->{return "IronMan";}。
View Code
2: 下面哪些接口是函数式接口?
public interfaceAdder{int add(int a, intb);
}public interface SmartAdder extendsAdder{int add(double a, doubleb);
}public interface Nothing{ }
答案:只有Adder是函数式接口。 SmartAdder不是函数式接口,因为它定义了两个叫作add的抽象方法(其中一个是从 Adder那里继承来的)。 Nothing也不是函数式接口,因为它没有声明抽象方法。
View Code
.