function源码解析与实践-凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 85540
  • 博文数量: 165
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1655
  • 用 户 组: 普通用户
  • 注册时间: 2022-09-26 14:37
文章分类

全部博文(165)

文章存档

2024年(2)

2023年(95)

2022年(68)

我的朋友
相关博文
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·

分类: java

2022-11-29 11:36:34

作者:陈昌浩

1 导读

if…else…在代码中经常使用,听说可以通过java 8的function接口来消灭if…else…!function接口是什么?如果通过function接口接口消灭if…else…呢?让我们一起来探索一下吧。

2 function接口

function接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,function接口可以被隐式转换为 lambda 表达式。可以通过functionalinterface注解来校验function接口的正确性。java 8允许在接口中加入具体方法。接口中的具体方法有两种,default方法和static方法。

@functionalinterface interface 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 源码
@functionalinterface public interface function {
    r apply(t t); default  function compose(functionsuper v, ? extends t> before) { objects.requirenonnull(before); return (v v) -> apply(before.apply(v));
    } default  function andthen(functionsuper r, ? extends v> after) { objects.requirenonnull(after); return (t t) -> after.apply(apply(t));
    } static  function 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 源码
@functionalinterface public 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 sup = suppliertest::new;
        system.out.println("调用一次");
        sup.get();
        system.out.println("调用二次");
        sup.get();
} 复制代码

执行结果:

如结果所示:supplier建立时并没有创建新类,每次调用get返回的值不是同一个。

3.3 consumer

consumer接收一个参数,没有返回值。

3.3.1 源码
@functionalinterface public interface consumer {
    void accept(t t);
    default consumer andthen(consumer 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 源码
@functionalinterface public 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 差异处理

原代码:

@data public class user { /**
     * 姓名
     */ private string name; /**
     * 年龄
     */ private int age; /**
     * 组员
     */ private list parters;
} public static void main(string[] args) {
        user user =new user(); if(user ==null ||user.getage() <18 ){ throw new runtimeexception("未成年!");
        }
} 复制代码

执行结果:

使用function接口后的代码:

@functionalinterface public 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);
        }
    });
} @functionalinterface public 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表达式完美结合,是非常重要的特性,可以极大的简化代码。


作者:京东云开发者
链接:
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
阅读(236) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图