【前言】 java8新特性html
java8中一个很是重要的特性就是lambda表达式,咱们能够把它当作是一种闭包,它容许把函数当作参数来使用,是面向函数式编程的思想,必定程度上可使代码看起来更加简洁。例如之前咱们使用匿名内部类来实现代码:java
//匿名内部类写法 new Thread(new Runnable() { @Override public void run() { System.out.println("内部类写法"); } }).start();
使用lambda则更加简洁:git
//lambda 写法 new Thread(() -> System.out.println("lambda写法")).start();
(paramters) -> expression;
或者github
(paramters) -> {statements;} 展开如: (Type1 param1, Type2 param2, Type2 param2, ...) -> { statement1; statement2; statement3; ... return statementX; }
示例:express
//入参为空 TestDemo no_param = () -> "hi, no param"; TestDemo no_param2 = () -> { return "hi, no param"; }; System.out.println(no_param.hi()); //单个参数 TestDemo2 param = name -> name; TestDemo2 param2 = name -> { return name;}; System.out.println(param.hei("hei, grils")); //多个参数 TestDemo3 multiple = (String hello, String name) -> hello + " " + name; //一条返回语句,能够省略大括号和return TestDemo3 multiple2 = (hello, name) -> hello + name; //多条处理语句,须要大括号和return TestDemo3 multiple3 = (hello, name) -> { System.out.println("进入内部"); return hello + name; }; System.out.println(multiple.greet("hello", "lambda"));
有如下几种类型编程
3.1 对象::实例方法,将lambda的参数当作方法的参数使用闭包
objectName::instanceMethod
示例:app
Consumer<String> sc = System.out::println; //等效 Consumer<String> sc2 = (x) -> System.out.println(x); sc.accept("618, 狂欢happy");
3.2 类::静态方法,将lambda的参数当作方法的参数使用编程语言
ClassName::staticMethod
示例:ide
//ClassName::staticMethod 类的静态方法:把表达式的参数值做为staticMethod方法的参数 Function<Integer, String> sf = String::valueOf; //等效 Function<Integer, String> sf2 = (x) -> String.valueOf(x); String apply1 = sf.apply(61888);
3.3 类::实例方法,将lambda的第一个参数当作方法的调用者,其余的参数做为方法的参数。开发中尽可能少些此类写法,减小后续维护成本。
ClassName::instanceMethod
示例:
//ClassName::instanceMethod 类的实例方法:把表达式的第一个参数当成instanceMethod的调用者,其余参数做为该方法的参数 BiPredicate<String, String> sbp = String::equals; //等效 BiPredicate<String, String> sbp2 = (x, y) -> x.equals(y); boolean test = sbp.test("a", "A");
无参的构造方法就是类::实例方法模型,如:
Supplier<User> us = User::new; //等效 Supplier<User> us2 = () -> new User(); //获取对象 User user = us.get();
当有参数时:
//一个参数,参数类型不一样则会编译出错 Function<Integer, User> uf = id -> new User(id); //或加括号 Function<Integer, User> uf2 = (id) -> new User(id); //等效 Function<Integer, User> uf3 = (Integer id) -> new User(id); User apply = uf.apply(61888); //两个参数 BiFunction<Integer, String, User> ubf = (id, name) -> new User(id, name); User 狂欢happy = ubf.apply(618, "狂欢happy");
接口A:
public interface A { String hi(); String greet(); default void hello() { System.out.println("A.hello"); } }
接口B:
public interface B { String hi(); String hh(); default void hello() { System.out.println("B.hello"); } }
类C实现A,B:
public class C implements A, B{ @Override public String hi() { return "C.hi"; } @Override public String greet() { return "C.greet"; } @Override public String hh() { return "C.hh"; } /** * 子类优先继承父类的方法, 若是父类没有相同签名的方法,才继承接口的默认方法。 * 编译报错解决1:覆盖法 */ @Override public void hello() { System.out.println("C.hello"); } /** * 编译报错解决2:指定实现的父接口 */ // @Override // public void hello() { // A.super.hello(); //// B.super.hello(); // } }
此时若不处理hello方法时,类C将编译出错,解决方式要么覆盖,要么指定实现父接口的该方法。
进一步测试继承具备相同方法的父类:
类D:
public class D { public void hello() { System.out.println("D.hello"); } }
类C继承类D:
public class C extends D implements A, B{ @Override public String hi() { return "C.hi"; } @Override public String greet() { return "C.greet"; } @Override public String hh() { return "C.hh"; } /** * 子类优先继承父类的方法, 若是父类没有相同签名的方法,才继承接口的默认方法。 * 编译报错解决1:覆盖法 */ // @Override // public void hello() { // System.out.println("C.hello"); // } /** * 编译报错解决2:指定实现的父接口 */ // @Override // public void hello() { // A.super.hello(); //// B.super.hello(); // } }
此时若不覆盖或指定父接口的方法时,类C将继承类D的hello方法。
java8引入lambda表达式是接收了函数式编程语言的思想,例如scala之类的,它将函数视为一等公民,可使用高阶函数等。
和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。