jdk8 新特性lambda表达式

首先说明下,jdk8的新特性forEach,Stream在遍历集合时,代码看上去简洁些,但效率会变低

好了,今天开始介绍新特性,先说lambda表达式

Python里有个匿名函数,用lambda定义,jdk8的lambda表达式就相当于一个匿名函数,只是功能强大一些

先说一个概念:

函数式编程:

函数式编程是种编程范式。是相对于命令式编程(常见于面向过程,如C语言),命令式编程是编写,理解和调试代码最容易的方法

举例说明:获取BufferedReader对象

命令式编程:

InputStream in=new InputStream("d:\\test.txt");
InputStreamReader isr=new InputStreamReader(in);
BufferedReader br=new BufferedReader(isr);

函数事编程:调用函数替代命令

BufferedReader br = new BufferedReader(new InputStreamReader(in))

 函数式接口(Functional Interface):

jdk8中新增了函数式接口,

函数式接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口(修饰符为defalut)。

以前认识的接口中所有方法必须都是抽象的,是不能有非抽象方法的,jdk更新过程中可能对某些接口进行扩展,但是如果在原有接口中加入抽象方法,那实现了该接口的类要全部重新写,为了解决更新接口但兼容以前版本的程序,就可以在函数式接口中可以增加defalut方法

Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)就是针对函数式接口使用的.因为lambda表达式没有方法名,所以针对的就是接口中的抽象方法,说明函数值接口中只能有一个抽象方法,不然天知道lambda重写的是哪个抽象方法

以前如果参数是接口类型的实例,要么自定义类实现接口,要么用匿名内部类,那lambda表达式的引入就可以让匿名内部类的编写变得简洁一些.

函数式接口,如Callable接口(java.util.concurrent.Callable)。

jdk8中新增了@FunctionalInterface注解来显示标注一个函数式接口,并不是所有函数式接口都被标注出来了。该注解主要用于编译级错误检查,加上该注解后,如果自定义接口不符合函数式接口的定义,会报错。当然有没有该注解不会影响是不是函数式接口的本质.

注解样式如下:

@FunctionalInterface
public interface Callable<V> {
   
    V call() throws Exception;
}

defalut方法

jdk8中允许接口中定义非抽象方法,在接口中的非抽象方法上使用default修饰即可,加入defalut方法是对接口的补充,好处就是提高程序的兼容性.接口中定义defalut方法变相让java支持多继承,因为可实现多个接口

实际上函数式接口可支持静态方法,继承自java.lang.Object类要重写的public方法,


lambda表达式

上面已经说过,lambda表达式只能用在重写函数式接口的抽象方法上,因为函数式接口只有一个抽象方法,编译器会认为lambda表达式写的方法就是接口的唯一的抽象方法

先看lambda的格式:

(类型 参数, 类型 参数, …, 类型 参数) -> {  代码块;  return 结果; }
注:参数类型可省略,编译器可以从上下文环境推断出lambda表达式的参数类型,故可以省略
  如箭头右边只有一条语句,则右边的一对大括号可省略
  当lambda表达式只有一个参数时,可以省略左边的小括号
  对有返回值的抽象方法,如果重写只有一行语句,可以省略掉return关键字,(同时必须省略一对大括号)

   

格式形如为

( )->{ } 
括号 向右的箭头 大括号(方法体)

示例:

自定义函数式接口


@FunctionalInterface
public interface MyInter {
	int add(int a, int b);

	// defalut修饰的方法
	default void sub(int a, int b) {
		System.out.println(a - b);
	}

	// 可写静态方法
	static String addString(String s1, String s2) {
		return s1 + s2;
	}

	// 重写继承自Object类的方法,必须是抽象方法,再被实现该接口的类重写
	// 这种继承自Object类的方法,不被接口认定为抽象方法(实际是抽象方法)
	@Override
	boolean equals(Object obj);
}

测试类:

public class Test01 {
	public static void main(String[] args) {
		//传统匿名内部类的写法
		MyInter mi = new MyInter() {
			@Override
			public int add(int a, int b) {
				int temp = a + b;
				return temp;
			}
		};
		System.out.println(mi.add(1, 2));
		
		//试用lambda表达式写匿名内部类
		MyInter mi2 = (a, b) -> {
			return a + b;
		};
		System.out.println(mi2.add(1, 2));
                // 省略return语句
		MyInter mi3 = (a, b) -> a + b;
		System.out.println(mi3.add(1, 2));
	
	}
}
out:
3
3
3

lambda表达式写多线程示例

public class Test02 {
	public static void main(String[] args) {
		// 以前写法
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i != 10; i++) {
					System.out.println(Thread.currentThread().getName() + " : " + i);// 打印0-9,包括9
				}
			}
		}, "t1");
		t1.start();
		// 用lambda表达式下多线程
		Thread t2 = new Thread(() -> {
			for (int i = 0; i < 10; i++) {
				System.out.println(Thread.currentThread().getName() + " : " + i);
			}
		}, "t2");
		t2.start();

	}
}
out:
t1 : 0
t1 : 1
t1 : 2
t1 : 3
t1 : 4
t1 : 5
t1 : 6
t1 : 7
t1 : 8
t1 : 9
t2 : 0
t2 : 1
t2 : 2
t2 : 3
t2 : 4
t2 : 5
t2 : 6
t2 : 7
t2 : 8
t2 : 9

参考:http://www.monkey1024.com/javase/706

猜你喜欢

转载自blog.csdn.net/sinat_41132860/article/details/84636634