作者:陈昌浩
1 导读
if…else…在代码中常常应用,据说能够通过Java 8的Function接口来毁灭if…else…!Function接口是什么?如果通过Function接口接口毁灭if…else…呢?让咱们一起来摸索一下吧。
2 Function接口
Function接口就是一个有且仅有一个形象办法,然而能够有多个非形象办法的接口,Function接口能够被隐式转换为 lambda 表达式。能够通过FunctionalInterface注解来校验Function接口的正确性。Java 8容许在接口中退出具体方法。接口中的具体方法有两种,default办法和static办法。
@FunctionalInterfaceinterface TestFunctionService{ void addHttp(String url);}
那么就能够应用Lambda表达式来示意该接口的一个实现。
TestFunctionService testFunctionService = url -> System.out.println("http:" + url);
2.1 FunctionalInterface
2.1.1 源码
@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface FunctionalInterface {}
2.1.2 阐明
上图是FunctionalInterface的注解阐明。通过下面的注解阐明,能够晓得FunctionalInterface是一个注解,用来阐明一个接口是函数式接口。 函数式接口只有一个形象办法。 能够有默认办法,因为默认办法有一个实现,所以不是形象的。函数接口的实例能够用lambda表达式、办法援用或构造函数援用创立。
FunctionalInterface会校验接口是否满足函数式接口:
- 类型必须是接口类型,不能是正文类型、枚举或类。
- 只能有一个形象办法。
- 能够有多个默认办法和静态方法。
- 能够显示笼罩java.lang.Object中的形象办法。
编译器会将满足函数式接口定义的任何接口视为函数式接口,而不论该接口申明中是否应用FunctionalInterface注解。
3 Function接口次要分类
Function接口次要分类:
- Function:Function函数的表现形式为接管一个参数,并返回一个值。
- Supplier:Supplier的表现形式为不承受参数、只返回数据。
- Consumer:Consumer接管一个参数,没有返回值。
- Runnable:Runnable的表现形式为即没有参数也没有返回值。
3.1 Function
Function函数的表现形式为接管一个参数,并返回一个值。
3.1.1 源码
@FunctionalInterfacepublic interface Function<T, R> { R apply(T t); default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } static <T> Function<T, T> identity() { return t -> t; }}
3.1.2 办法阐明
- apply:形象办法。将此函数利用于给定的参数。参数t通过具体的实现返回R。
- compose:default办法。返回一个复合函数,首先执行fefore函数利用于输出,而后将该函数利用于后果。如果任意一个函数的求值引发异样,则将其传递给组合函数的调用者。
- andThen:default办法。返回一个复合函数,该复合函数首先对其利用此函数它的输出,而后对后果利用after函数。如果任意一个函数的求值引发异样,则将其传递给组合函数的调用者。
- identity:static办法。返回一个始终返回其输出参数的函数。
3.1.3 办法举例
1)apply
测试代码:
public String upString(String str){ Function<String, String> function1 = s -> s.toUpperCase(); return function1.apply(str);} public static void main(String[] args) { System.out.println(upString("hello!")); }
通过apply调用具体的实现。执行后果:
2)compose
测试代码:
public static void main(String[] args) { Function<String, String> function1 = s -> s.toUpperCase(); Function<String, String> function2 = s -> "my name is "+s; String result = function1.compose(function2).apply("zhangSan"); System.out.println(result);}
执行后果
如后果所示:compose 先执行function2 后执行function1。
3)andThen
测试代码:
public static void main(String[] args) { Function<String, String> function1 = s -> s.toUpperCase(); Function<String, String> function2 = s -> "my name is "+s; String result = function1.andThen(function2).apply("zhangSan"); System.out.println(result);}
执行后果:
如后果所示:
andThen先执行function1 后执行function2。
- identity
测试代码:
public static void main(String[] args) { Stream<String> stream = Stream.of("order", "good", "lab", "warehouse"); Map<String, Integer> map = stream.collect(Collectors.toMap(Function.identity(), String::length)); System.out.println(map);}
执行后果:
3.2 Supplier
Supplier的表现形式为不承受参数、只返回数据。
3.2.1 源码
@FunctionalInterfacepublic interface Supplier<T> { /** * Gets a result. * * @return a result */ T get();}
3.2.2 办法阐明
get:形象办法。通过实现返回T。
3.2.3 办法举例
public class SupplierTest { SupplierTest(){ System.out.println(Math.random()); System.out.println(this.toString()); }} public static void main(String[] args) { Supplier<SupplierTest> sup = SupplierTest::new; System.out.println("调用一次"); sup.get(); System.out.println("调用二次"); sup.get();}
执行后果:
如后果所示:Supplier建设时并没有创立新类,每次调用get返回的值不是同一个。
3.3 Consumer
Consumer接管一个参数,没有返回值。
3.3.1 源码
@FunctionalInterfacepublic interface Consumer<T> { void accept(T t); default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; }}
3.3.2 办法阐明
- accept:对给定参数T执行一些操作。
- andThen:按程序执行Consumer -> after ,如果执行操作引发异样,该异样被传递给调用者。
3.3.3 办法举例
public static void main(String[] args) { Consumer<String> consumer = s -> System.out.println("consumer_"+s); Consumer<String> after = s -> System.out.println("after_"+s); consumer.accept("isReady"); System.out.println("========================"); consumer.andThen(after).accept("is coming");}
执行后果:
如后果所示:对同一个参数T,通过andThen 办法,先执行consumer,再执行fater。
3.4 Runnable
Runnable:Runnable的表现形式为即没有参数也没有返回值。
3.4.1 源码
@FunctionalInterfacepublic interface Runnable { public abstract void run();}
3.4.2 办法阐明
run:形象办法。run办法实现具体的内容,须要将Runnale放入到Thread中,通过Thread类中的start()办法启动线程,执行run中的内容。
3.4.3 办法举例
public class TestRun implements Runnable { @Override public void run() { System.out.println("TestRun is running!"); }} public static void main(String[] args) { Thread thread = new Thread(new TestRun()); thread.start(); }
执行后果:
如后果所示:当线程履行start办法时,执行Runnable 的run办法中的内容。
4 Function接口用法
Function的主要用途是能够通过lambda 表达式实现办法的内容。
4.1 差别解决
原代码:
@Datapublic class User { /** * 姓名 */ private String name; /** * 年龄 */ private int age; /** * 组员 */ private List<User> parters;} public static void main(String[] args) { User user =new User(); if(user ==null ||user.getAge() <18 ){ throw new RuntimeException("未成年!"); }}
执行后果:
应用Function接口后的代码:
@FunctionalInterfacepublic interface testFunctionInfe { /** * 输出异样信息 * @param message */ void showExceptionMessage(String message);} public static testFunctionInfe doException(boolean flag){ return (message -> { if (flag){ throw new RuntimeException(message); } }); } public static void main(String[] args) { User user =new User(); doException(user ==null ||user.getAge() <18).showExceptionMessage("未成年!");}
执行后果:
应用function接口前后都抛出了指定的异样信息。
4.2 解决if…else…
原代码:
public static void main(String[] args) { User user =new User(); if(user==null){ System.out.println("新增用户"); }else { System.out.println("更新用户"); }}
应用Function接口后的代码:
public static void main(String[] args) { User user =new User(); Consumer trueConsumer = o -> { System.out.println("新增用户"); }; Consumer falseConsumer= o -> { System.out.println("更新用户"); }; trueOrFalseMethdo(user).showExceptionMessage(trueConsumer,falseConsumer);}public static testFunctionInfe trueOrFalseMethdo(User user){ return ((trueConsumer, falseConsumer) -> { if(user==null){ trueConsumer.accept(user); }else { falseConsumer.accept(user); } });}@FunctionalInterfacepublic interface testFunctionInfe { /** * 不同分解决不同的事件 * @param trueConsumer * @param falseConsumer */ void showExceptionMessage(Consumer trueConsumer,Consumer falseConsumer);}
执行后果:
4.3 解决多个if
原代码:
public static void main(String[] args) { String flag=""; if("A".equals(flag)){ System.out.println("我是A"); }else if ("B".equals(flag)) { System.out.println("我是B"); }else if ("C".equals(flag)) { System.out.println("我是C"); }else { System.out.println("没有对应的指令"); }}
应用Function接口后的代码:
public static void main(String[] args) { String flag="B"; Map<String, Runnable> map =initFunctionMap(); trueOrFalseMethdo(map.get(flag)==null).showExceptionMessage(()->{ System.out.println("没有相应指令"); },map.get(flag));}public static Map<String, Runnable> initFunctionMap(){ Map<String,Runnable> result = Maps.newHashMap(); result.put("A",()->{System.out.println("我是A");}); result.put("B",()->{System.out.println("我是B");}); result.put("C",()->{System.out.println("我是C");}); return result;}public static testFunctionInfe trueOrFalseMethdo(boolean flag){ return ((runnable, falseConsumer) -> { if(flag){ runnable.run(); }else { falseConsumer.run(); } });}
执行后果:
5 总结
Function函数式接口是java 8新退出的个性,能够和lambda表达式完满联合,是十分重要的个性,能够极大的简化代码。