jdk1.8新特性
2015-04-24 21:56
295 查看
在jdk1.8当中,有如下新特性,分为两大类:1.接口中可以实现方法了。2.java8中支持lambda表达式
那么当然,首先需要下载jdk1.8,然后安装配置环境变量,这些都操作了以后,并且在命令行下java -version可以看到已经切换到java8了,可是在eclipse中编译就是有问题,这个问题i怎么处理,看下面:
1.在eclipse当中,点击help ->eclipse market place,然后按照如下图片操作即可:
在红色选中的那一行,点击install即可,这里由于我已经安装过了,所示是update。
首先看看java8中,关于接口的变化
1.接口可以实现static的方法,并且调用的时候是用:接口名.方法名();
2.接口可以实现default的方法,调用的时候,必须用该接口的实现类的对象来调用
对于使用default实现的方法,需要使用接口实现类的对象来调用
我新建一个类,来实现EightInterface接口:
hello 小明
child's a + b = 5
那么问题来了,如果我在两个接口当中都实现了拥有同样方法名的default方法,此时如果一个类同时实现这两个接口,那么调用的时候,具体是调用哪个呢?我们来看一个demo:
新建两个接口,InterfaceA,InterfaceB,并且实现两个同样方法名的default方法,如下:
结论:
1.如果一个类实现的多个接口当中定义了同样的静态方法,不允许使用实现类名.方法名()这样的写法
2.如果一个类实现多个接口,在多个接口当中定义了相同名称的default方法,此时编译报错,必须实现接口定义相同名称的default方法。
java8中的lambda表达式:
lambda表达式,本质上是一种匿名的内部类,使用该表达式,可以让我们的代码更加的简洁易懂。例如:
lambda表达式由三个部分组成:参数列表,箭头->,语句块。书写格式如下:
(参数1,参数2) ->{
方法体
}
当然如果我们的方法体只有一句代码,亦可以去掉{} ,如下:
(参数1,参数2) -> 方法体
有一个这样的方法:
public void sayHi(String name) {
System.out.println("hello:"+name);
}
如果用lambda写出来就是这个样子的:
(String name) -> System.out.println("hello:"+name);
当然,lambda中还会根据上下文环境自动判别参数的类型,此时参数的类型就可以省去了,如下:
(name) -> System.out.println("hello:"+name);
是不是很简单呢?写起来更快一些。再来一些例子:
如果你的方法并不改变任何方法参数,比如只是输出,那么可以简写如下:
() -> System.out.println("Hello Lambda Expressions");
如果你的方法接受两个方法参数,如下:
(int even, int odd) -> even + odd
注意:如果“语句或语句块”有返回值时,如果只有一条语句则可以不输写“return”语句,编译器会自动处理,否则必须加上
说了这么多,那么lambda表达式,都会用在哪些地方呢?其实lambda表达式主要用于替换之前使用的内部匿名类,各种回调,事件回调等。
1.代替匿名内部类:
在之前实现runnable是这样写的:
2.实现事件处理:
3.遍历list集合:
4.使用lambda表达式和函数式接口:
Java 8加入了一个新的包java.util.function,其中有一个接口java.util.function.Predicate是支持Lambda函数编程:
我们还可以将上边的filter进一步简化:
其中Predicate类中提供了如下方法可以执行and(),or()方法进行逻辑操作,如下:
both startWithJ and strLength is :Java
下面使用lambda表达式,来对list进行操作,我们是list中每个数字增加8,如下:
5.对集合中每个元素应用函数:
可以看到使用Lambda表达式不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。
那么当然,首先需要下载jdk1.8,然后安装配置环境变量,这些都操作了以后,并且在命令行下java -version可以看到已经切换到java8了,可是在eclipse中编译就是有问题,这个问题i怎么处理,看下面:
1.在eclipse当中,点击help ->eclipse market place,然后按照如下图片操作即可:
在红色选中的那一行,点击install即可,这里由于我已经安装过了,所示是update。
首先看看java8中,关于接口的变化
1.接口可以实现static的方法,并且调用的时候是用:接口名.方法名();
2.接口可以实现default的方法,调用的时候,必须用该接口的实现类的对象来调用
package com.test.jdk.eight; public interface EightInterface { //jdk1.8中,接口可以实现static的方法,并且调用的时候是用:接口名.方法名(); public static String hello(String name) { return "hello "+name; } //jdk1.8中,接口可以实现default的方法,调用的时候,必须用该接口的实现类的对象来调用 public default void add(int a,int b) { System.out.println("a + b ="+(a+b)); } }对于使用static定义实现的方法,可以在类中直接使用:接口名.方法名();来调用
对于使用default实现的方法,需要使用接口实现类的对象来调用
我新建一个类,来实现EightInterface接口:
package com.test.jdk.eight; public class EightInterfaceImpl implements EightInterface { /** * 当我们试图重写中的default方法时候,系统提示 * Default methods are allowed only in interfaces with source level 1.8 or * greater.(default方法只能在jdk1.8或更高的版本上并且只能在接口当中使用。) */ @Override public void add(int a, int b) { System.out.println("child's a + b = "+(a + b) ); } }此时EightInterfaceImpl已经实现并重写了default方法,此时调用如下:
package com.test.jdk.eight; public class TestInterface { public static void main(String[] args) { String result = EightInterface.hello("小明"); System.out.println(result); EightInterfaceImpl interfaceImpl = new EightInterfaceImpl(); interfaceImpl.add(2,3); } }打印结果如下:
hello 小明
child's a + b = 5
那么问题来了,如果我在两个接口当中都实现了拥有同样方法名的default方法,此时如果一个类同时实现这两个接口,那么调用的时候,具体是调用哪个呢?我们来看一个demo:
新建两个接口,InterfaceA,InterfaceB,并且实现两个同样方法名的default方法,如下:
package com.test.inter.muti; public interface InterfaceA { public static void a() { System.out.println("InterfaceA 中a方法的实现"); } //定义A接口中的默认方法 public default void defaultMethod() { System.out.println("InterfaceA 中的默认方法。。。。。"); } }
package com.test.inter.muti; public interface InterfaceB { public static void a() { System.out.println("InterfaceB 中a方法的实现"); } //定义B接口中的默认方法 public default void defaultMethod() { System.out.println("InterfaceB 中的默认方法。。。。。"); } }此时,我新建一个类,实现上面的两个接口:
package com.test.inter.muti; public interface InterfaceB { public static void a() { System.out.println("InterfaceB 中a方法的实现"); } //定义B接口中的默认方法 public default void defaultMethod() { System.out.println("InterfaceB 中的默认方法。。。。。"); } }此时,我新建一个类,实现上面定义的两个接口:
public class InterfaceImpl implements InterfaceA, InterfaceB { public void defaultMethod() { System.out.println("实现类实现的方法。。。。"); } }这里我们注意到,如果该类实现的两个接口都实现了同样方法名的default方法的话,那么我们必须重写该方法,否则编译都不会过的,还有如果两个类中都实现了同样方法名的static方法,那么此时在实现类中不能通过:实现类名.方法名()来调用该静态方法。
结论:
1.如果一个类实现的多个接口当中定义了同样的静态方法,不允许使用实现类名.方法名()这样的写法
2.如果一个类实现多个接口,在多个接口当中定义了相同名称的default方法,此时编译报错,必须实现接口定义相同名称的default方法。
java8中的lambda表达式:
lambda表达式,本质上是一种匿名的内部类,使用该表达式,可以让我们的代码更加的简洁易懂。例如:
lambda表达式由三个部分组成:参数列表,箭头->,语句块。书写格式如下:
(参数1,参数2) ->{
方法体
}
当然如果我们的方法体只有一句代码,亦可以去掉{} ,如下:
(参数1,参数2) -> 方法体
有一个这样的方法:
public void sayHi(String name) {
System.out.println("hello:"+name);
}
如果用lambda写出来就是这个样子的:
(String name) -> System.out.println("hello:"+name);
当然,lambda中还会根据上下文环境自动判别参数的类型,此时参数的类型就可以省去了,如下:
(name) -> System.out.println("hello:"+name);
是不是很简单呢?写起来更快一些。再来一些例子:
如果你的方法并不改变任何方法参数,比如只是输出,那么可以简写如下:
() -> System.out.println("Hello Lambda Expressions");
如果你的方法接受两个方法参数,如下:
(int even, int odd) -> even + odd
注意:如果“语句或语句块”有返回值时,如果只有一条语句则可以不输写“return”语句,编译器会自动处理,否则必须加上
说了这么多,那么lambda表达式,都会用在哪些地方呢?其实lambda表达式主要用于替换之前使用的内部匿名类,各种回调,事件回调等。
1.代替匿名内部类:
在之前实现runnable是这样写的:
new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 3; i++) { System.out.println("use runnable is :"+i); <span style="white-space:pre"> </span>} } }).start();那么如果使用lambda表达式,可以这么写,会有同样的效果:
new Thread(()->{ for (int i = 0; i < 3; i++) { System.out.println("use lambda is :"+i); } }).start();
2.实现事件处理:
// Before Java 8: JButton show = new JButton("Show"); show.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("without lambda expression is boring"); } }); // Java 8 way: show.addActionListener((e) -> { System.out.println("Action !! Lambda expressions Rocks"); });
3.遍历list集合:
List<String>lists = Arrays.asList("aaa","bbb","ccc","ddd"); for (String string : lists) { System.out.print(string); }使用lambda遍历list集合:
List<String>lists = Arrays.asList("aaa","bbb","ccc","ddd"); lists.forEach((str) -> System.out.println(str));在这里lambda可以自动辨别str参数的类型,因此不需要申请该参数类型。
4.使用lambda表达式和函数式接口:
Java 8加入了一个新的包java.util.function,其中有一个接口java.util.function.Predicate是支持Lambda函数编程:
public static void main(String[] args) { List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp"); System.out.println("Languages which starts with J :"); filter(languages, (str)->((String) str).startsWith("J")); System.out.println("Languages which ends with a "); filter(languages, (str)->((String) str).endsWith("a")); System.out.println("Print all languages :"); filter(languages, (str)->true); System.out.println("Print no language : "); filter(languages, (str)->false); System.out.println("Print language whose length greater than 4:"); filter(languages, (str)->((String) str).length() > 4); } public static void filter(List<String> names, Predicate condition) { for(String name: names) { if(condition.test(name)) { System.out.println(name + " "); } } }
我们还可以将上边的filter进一步简化:
public static void filter(List names, Predicate condition) { names.stream().filter((name) -> (condition.test(name))) .forEach((name) -> {System.out.println(name + " "); });来自Stream API 的filter方法能够接受 Predicate参数, 能够允许测试多个条件。
其中Predicate类中提供了如下方法可以执行and(),or()方法进行逻辑操作,如下:
List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp"); Predicate<String>startWithJ = (str) -> str.startsWith("J"); Predicate<String>strLength = (str) -> str.length() == 4; languages.stream().filter(startWithJ.and(strLength)).forEach((str) -> System.out.println("both startWithJ and strLength is :"+str));此时,由于只有Java这一项满足条件,所以打印结果如下:
both startWithJ and strLength is :Java
下面使用lambda表达式,来对list进行操作,我们是list中每个数字增加8,如下:
List<Integer>lists = Arrays.asList(10,20,30,40); lists.stream().map((xInt) -> xInt + 8).forEach((xInt) -> System.out.println("after lambda is :"+xInt));
5.对集合中每个元素应用函数:
List<String> countries = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada"); String result = countries.stream().map((str) -> str.toUpperCase()).collect(Collectors.joining(",")); System.out.println(result);
可以看到使用Lambda表达式不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。
相关文章推荐
- [Java]_[JDK1.8新特性]
- 杰神之Java接口JDK1.8新特性
- [转]JDK1.7和JDK1.8的新特性
- jdk1.8新特性 分组统计及格式化
- 菜鸟记录之JDK1.8十大新特性
- jdk1.8新特性-接口
- jdk1.8新特性
- Java JDK1.8新特性
- JDK1.8新特性(二)Lambda表达式入门
- 总结:JDK1.5-JDK1.8各个新特性
- jdk1.8新特性之lambda表达式
- jdk1.8新特性
- jdk1.8 新特性之 default,static 接口关键字
- JDK1.8新特性
- JAVA基础【1.5】《Java核心技术1》Java程序设计概述-Java JDK1.8新特性【收集】
- JDK1.5~1.8新特性
- jdk1.8 新特性之 forEach 循环遍历
- Jdk1.8特性
- JDK1.8新特性
- Java JDK1.8新特性Lambda 表达式