java8中最大的变化就是引入了Lambda表达式,这是一种函数式编程的方式。
1.lambda表达式的形式
java8的lambda表达式语法如下:
(paramters)->expression;
或者
(parameters)->{statements;};
例如:
()->10;
(x)->x+10;
(x,y)->x+y;
(int x,int y)->x+y;
(int x)->x+10;
或者:
()->{10;}
(x)->{x+10;}
(x,y)->{x+y;}
(int x,int y)->{x+y;}
(int x)->{x+10;}
lambda表达式由三部分组成:
1.parameters:方法中的形参列表,这里的参数是函数式接口里的参数,参数类型可以明确声明也可以隐藏。
2.->:可以理解为“被用于”的意思
3.方法体:可以是表达式也可以是代码块,是函数式接口里方法的具体实现。代码块根据需要使用的方法自行定义是否返回值。
2.lambda表达式的具体实现
2.1 遍历集合
List list= Arrays.asList("lamdbas","Default");
list.forEach(n->{System.out.println(n); System.out.println(n+"23"); });
执行结果如下:
lamdbas
lamdbas23
Default
Default23
2.2带参函数的简写
List list= Arrays.asList("da","abc","c","q","d"); Collections.sort(list,(String a,String b)->{ if(a==null){ return 1; }else if(b==null){ return -1; }else{ return a.length()-b.length(); } }); list.forEach(System.out::println);
执行结果如下
c
q
d
da
abc
简写的依据
能够使用lambda的依据就是必须有相应的函数接口(函数接口,是指内部只有一个抽象方法的接口)。
2.3 自定义函数接口
自定义函数接口很简单,只要编写一个只有一个抽象方法的接口即可。
@FunctionalInterface //自定义函数接口注解,可写可不写,写了会检查是否符合函数接口规范 interface Converter<F,T>{ T convert(F a); }
//使用lambda表达式调用
Converter<String,Integer> a=str->{System.out.println(str);return Integer.valueOf(str);}; a.convert("1231");
执行结果如下
1231
解释:此功能的主要作用是输出string对象并将string类型的对象转换成Integer;
标准的函数式接口有
-
Function<T, R>:接受一个参数T,返回结果R
-
Predicate<T>:接受一个参数T,返回boolean
-
Supplier<T>:不接受任何参数,返回结果T
-
Consumer<T>:接受一个参数T,不返回结果
-
UnaryOperator<T>:继承自Function<T, T>,接受一个参数T,返回相同类型T的结果
-
BiFunction<T, U, R>:接受两个参数T和U,返回结果R
-
BinaryOperator<T>:继承自BiFunction<T, T, T>,接受两个相同类型T的参数,返回相同类型T的结果
-
……
3.方法引用
方法引用式lambda表达式的一种简化写法。具体的结构如下:
Object::methodName
左边式类名或者实例名,中间式方法引用符号"::",右边式相应的方法名,方法引用分为三类:
1.静态方法引用
public class StaticFunction { @FunctionalInterface public interface Converter<T,F>{ F convert(T a); } static String func(String a){ return a+"abc"; } @Test public void test(){ Converter<String,String> a=StaticFunction::func; System.out.println(a.convert("123")); } }
结果如下
123abc
2.实例方法引用
public class StaticFunction { @FunctionalInterface public interface Converter<T,F>{ F convert(T a); } String func(String a){ return a+"abc"; } @Test public void test(){ StaticFunction a=new StaticFunction(); Converter<String,String> b=a::func; System.out.println(b.convert("123")); } }
结果如下
123abc
3.构造方法引用
//创建一个Animal的父类
@Data public class Animal { private String name; private int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void behavior(){ }}
//创建一个Dog的子类
public class Dog extends Animal{ public Dog(String name,int age){ super(name,age); } @Override public void behavior(){ System.out.println("this is a dog"); } }//创建一个Bird的子类
public class Bird extends Animal { public Bird(String name, int age) { super(name, age); } @Override public void behavior(){ System.out.println("this is a bird"); } }//定义工厂的函数式接口
@FunctionalInterface interface Factory<T extends Animal>{ T create (String name,int age); }//创建测试
@Test public void test(){ Animal.Factory<Animal> dogFactory=Dog::new; Animal dog=dogFactory.create("a",1); if(dog instanceof Dog){ dog.behavior(); } Animal.Factory<Bird> birdFactory=Bird::new; Bird bird=birdFactory.create("b",2); if(bird instanceof Bird){ bird.behavior(); } }
结果如下
this is a dog
this is a bird
4.lambda的作用域
在lambd表达式外部的局部变量会被JVM隐式的编译成final类型,因此只能访问外而不能修改
public class ReferenceTest {
@Test
public void test() {
int n = 9;
Calculate calculate = param -> {
//n=10; 编译错误
return n + param;
};
calculate.calculate(1);
}
@FunctionalInterface
interface Calculate {
int calculate(int value);
}
}
在lambda表达式内部,对静态变量和成员变量可读可写
public class Reference { @FunctionalInterface public interface Refer{ int print(); } public int count=1; public static int sum=2; @Test public void test(){ System.out.println(count); System.out.println(sum); Refer re=()->{ count=3; sum=4; return count+sum; }; System.out.println(re.print()); System.out.println(count); System.out.println(sum); } }
输出结果为
1
2
7
3
4
需要注意的是只有在执行了re.print()这个方法之后成员变量和静态变量的值才会改变。