多平台统一管理软件接口,如何实现多平台统一管理软件接口
135
2024-02-01
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。
我们常用的Runnable接口就是个典型的函数式接口,我们可以看到它有且仅有一个抽象方法run。并且可以看到一个注解@FunctionalInterface,这个注解的作用是强制你的接口只有一个抽象方法。
如果有多个话直接会报错,如图:
idea错误提示:
编译时错误提示:
这里当你写了第二个方法时,编译就无法通过,idea甚至在编码阶段就行了提示。
我们直接上代码,首先定义一个函数式接口
@FunctionalInterface public interface SingleAbstraMethodInterface { public abstract void singleMethod(); }我们定一个test类,封装一个方法,将SingleAbstraMethodInterface当做参数传入方法,并打印一句话
public class Test { public void testMethod(SingleAbstraMethodInterface single){ System.out.println("即将执行函数式接口外部定义方法"); single.singleMethod(); } public static void main(String[] args) { Test test = new Test(); test.testMethod(new SingleAbstraMethodInterface() { @Override public void singleMethod() { System.out.println("执行函数式接口定义方法"); } }); } }执行结果:
即将执行函数式接口外部定义方法
执行函数式接口定义方法是不是和我们预期结果一样。这个过程是不是有的同学已经发现,怎么这么像jdk里面的一些接口的使用,比如常用的Runnable接口。
我们来看看代码。
public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.out.println("run方法执行了"); } }).start(); }再看下Runnable接口源码,是不是一样
@FunctionalInterface public interface Runnable { public abstract void run(); }这时,有的同学会说,我用Runnable接口可不是这么用的,我的写法比你优雅,我是这么写的。
没错函数式接口,函数式编程,我们可以使用lambda表达式的写法,可以让代码更优雅,具体可以参照我的前一篇帖子。Java8之Lambda表达式
public static void main(String[] args) { new Thread(()-> { System.out.println("run方法执行了"); }).start(); }java.lang.Runnable,
java.awt.event.ActionListener,
java.util.Comparator,
java.util.concurrent.Callablejava.util.function包下的接口,如Consumer、Predicate、Supplier等
其实,jdk中给我们提供了很多的函数式接口,我们平时都会用到,只不过大家没有注意到而已,这里我结合实际代码讲解几个常用的函数式接口。想想大家平时常常用到stream流的各种方法来处理list。我看去stream类中看一下它提供的方法。可以看到有几个出镜率较高的函数式接口
SupplierComsumerPredicateFunctionSupplier接口的get方法没有入参,返回一个泛型T对象。
我们来看几个使用 的实例。
@Data @AllArgsConstructor @NoArgsConstructor public class Girl { private String name; private Double size; private Double price; public static Girl create(final Supplier<Girl> supplier) { return supplier.get(); } public static void main(String[] args) { //创建对象 Girl girl1 = Girl.create(Girl::new); Girl girl2 = Girl.create(()-> new Girl("lily",33d,1700d)); Girl girl = null; //orElseGet Girl girl3 = Optional.ofNullable(girl).orElseGet(Girl::new); } }需要注意的是,我没每调用一次get方法,都会重新创建一个对象。
orElseGet方法入参同样也是Supplier,这里对girl实例进行判断,通过Supplier实现了懒加载,也就是说只有当判断girl为null时,才会通过orElseGet方法创建新的对象并且返回。不得不说这个设计是非常的巧妙。
源码如下:
@FunctionalInterface public interface Consumer<T> { /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); /** * Returns a composed {@code Consumer} that performs, in sequence, this * operation followed by the {@code after} operation. If performing either * operation throws an exception, it is relayed to the caller of the * composed operation. If performing this operation throws an exception, * the {@code after} operation will not be performed. * * @param after the operation to perform after this operation * @return a composed {@code Consumer} that performs in sequence this * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }可以看到accept方法接受一个对象,没有返回值。
那么我们来实战,首先使用Lambda表达式声明一个Supplier的实例,它是用来创建Girl实例;再使用Lambda表达式声明一个Consumer的实例,它是用于打印出Girl实例的toString信息;最后Consumer消费了Supplier生产的Girl。
我们常用的forEach方法入参也是Consumer。
使用代码如下:
Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d); Consumer<Girl> consumer = (Girl g)->{ System.out.println(g.toString()); }; consumer.accept(supplier.get()); ArrayList<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5); list.forEach(System.out::println);可以看到test方法接受一个对象,返回boolean类型,这个函数显然是用来判断真假。
那么我们用这个接口来构造一个判断女孩子条件的示例,还有我们常用的stream流中,filter的入参也是Predicate,代码如下:
Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d); Predicate<Girl> girl36d = (Girl g)-> Objects.equals(g.getSize(),36d); Predicate<Girl> girl33d = (Girl g)-> Objects.equals(g.getSize(),33d); boolean test33 = girl33d.test(supplier.get()); boolean test36 = girl36d.test(supplier.get()); System.out.println(supplier.get().getName() +"是否为[36d] :"+test36); System.out.println(supplier.get().getName() +"是否为[33d] :"+test33);结果为:
lucy是否为[36d] :false
lucy是否为[33d] :trueArrayList<Girl> list = Lists.newArrayList(); list.add(new Girl("露西", 33d, 2000d)); list.add(new Girl("格蕾丝", 36d, 3000d)); list.add(new Girl("安娜", 28d, 1500d)); list.add(new Girl("克瑞斯", 31d, 1800d)); Predicate<Girl> greaterThan30d = (Girl g)-> g.getSize()>=30d; list.stream().filter(greaterThan30d).forEach(System.out::println);结果如下:
Girl(name=露西, size=33.0, price=2000.0)
Girl(name=格蕾丝, size=36.0, price=3000.0)
Girl(name=克瑞斯, size=31.0, price=1800.0)这个看到apply接口接收一个泛型为T的入参,返回一个泛型为R的返回值,所以它的用途和Supplier还是略有区别。还是一样我们举个栗子用代码来说明:
Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d); Function<Girl,String> girlMark = (Girl g)-> g.getName()+"的尺寸是"+g.getSize()+",每次能赚"+g.getPrice()+"。"; System.out.println(girlMark.apply(supplier.get()));我们可以看到funtion接口接收Girl对象实例,对girl的成员变量进行拼接,返回girl的描述信息。其基本用法就是如此。
lucy的尺寸是33.0,每次能赚1700.0。
这里我列举一些Supplier相关接口
a.Supplier相关拓展接口
接口名称方法名称方法签名Supplierget() -> TBooleanSuppliergetAsBoolean() -> booleanDoubleSuppliergetAsDouble() -> doubleIntSuppliergetAsInt() -> intLongSuppliergetAsLong() -> longb.Comsumer相关拓展接口
接口名称方法名称方法签名Consumeraccept(T) -> voidDoubleConsumeraccept(double) -> voidIntConsumeraccept(int) -> voidLongConsumeraccept(long) -> voidObjDoubleConsumeraccept(T, double) -> voObjIntConsumeraccept(T, int) -> voidObjLongConsumeraccept(T, long) -> voidc.Predicate相关拓展接口
接口名称方法名称方法签名Predicatetest(T) -> booleanBiPredicatetest(T, U) -> booleanDoublePredicatetest(double) -> boolIntPredicatetest(int) -> booleanLongPredicatetest(long) -> booleand.Function相关的接口
接口名称方法名称方法签名Functionapply(T) -> RBiFunctionapply(T, U) -> RDoubleFunctionapply(double) -> RDoubleToIntFunctionapplyAsInt(double) -> intDoubleToLongFunctionapplyAsLong(double) -> longIntFunctionapply(int) -> RIntToDoubleFunctionapplyAsDouble(int) -> doubleIntToLongFunctionapplyAsLong(int) -> longLongFunctionapply(long) -> RLongToDoubleFunctionapplyAsDouble(long) -> doubleLongToIntFunctionapplyAsInt(long) -> intToDoubleFunctionapplyAsDouble(T) -> doubleToDoubleBiFunctionapplyAsDouble(T, U) -> doubleToIntFunctionapplyAsInt(T) -> intToIntBiFunctionapplyAsInt(T, U) -> intToLongFunctionapplyAsLong(T) -> longToLongBiFunctionapplyAsLong(T, U) -> long前言随着现在实景地图的如火如荼建设,无人机等航拍测绘手段的不断升级,我们在获取全景照片或者正射影像,全景视频等数据上更加快速、便捷。由于无人机本身不进行相关数据的处理,比如全景地图的 ...
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~