您的位置:首页 > 编程语言 > Java开发

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的方法,调用的时候,必须用该接口的实现类的对象来调用

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表达式不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: