在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的方法,调用的时候,必须用该接口的实现类的对象来调用
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");
});
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表达式不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。