java的java8 自定义函数接口口 有对应没有任何参数的吗

必看:深入学习Java8中的函数式接口
点击上方“云栖社区”可以订阅哦
目前由于系统已经全面切换为JDK8,所以有必要系统的了解一下Java8的一些新特性,以便后续在日常工作中可以使用一些高级特性来提高编程效率。
因为Java8引入了函数式接口,在java.util.function包含了几大类函数式接口声明。这里第一篇主要研究一下Function相关的接口。
FunctionalInterface注解
Java8的新引入,包含函数式的设计,接口都有@FunctionalInterface的注解。就像这个注解的注释说明一样,它注解在接口层面,且注解的接口要有且仅有一个抽象方法。具体就是说,注解在Inteface上,且interface里只能有一个抽象方法,可以有default方法。因为从语义上来讲,一个函数式接口需要通过一个***逻辑上的***方法表达一个单一函数。那理解这个单一就很重要了,单一不是说限制你一个interface里只有一个抽象方法,单是多个方法的其他方法需要是继承自Object的public方法,或者你要想绕过,就自己实现default。函数式接口自己本身一定是只有一个抽象方法。同时,如果是Object类的public方法,也是不允许的。官方的说明翻译如下:
如果一个接口I,I有一组抽象方法集合M,且这些方法都不是Object类的public签名方法,那么如果存在一个M中的方法m,满足:
m的签名是所有M中方法签名的子签名。
m对于M中的每个方法都是返回类型可替换的。 此时,接口I是一个函数式接口。
怎么理解,看几个例子。
比如:你声明一个接口:
这会编译错,编译器会告诉你*no target method*。而如果加一个方法:
这就OK了,一个函数式接口声明好了。再加一个呢?
不ok,明确说了只有一个抽象方法嘛。但是如果换一种函数签名:
错误依旧,因为这个方法签名是Object类的public方法。而再改一下:
这就OK了。一个抽象方法,一个Object的public方法,相安无事。Object还有其他方法,clone方法试试会怎么样?
这又不行了,因为前面明确说了,要是Object的public方法,而clone是protected的。
所以总结一句话就是:
函数式接口,有且仅有一个抽象方法,Object的public方法除外。
因为Java本身支持多接口实现,你定义一个Class可以implements多个interface。所以这个限制也没什么影响,如果想约定一个函数式接口来统一,也可以做一些默认的实现来达到一个接口多个抽象方法的目的,比如下面这种做法:
一个普通接口NonFunc:
函数式接口Func:
实现的测试类:
函数式接口的一大特性就是可以被lambda表达式和函数引用表达式代替。也就是说声明这样的接口,是可以灵活的以方法来传参。看个例子:
上面例子列举了一个lambda模式和一个方法引用模式,这样就可以利用函数式编程强大的能力,将方法作为参数了。
另一个大的话题是针对上文的***逻辑上的方法***。所谓逻辑上,就是说当你出现函数式接口多重继承其他接口时,如果继承的多个接口有相同的方法签名,那么也是OK的。而这种相同签名的方法,也包括了泛型的情况,以下的声明中的Z接口,都是函数式接口。
但是要注意的是,这种泛型的支持,是因为函数式接口的官方声明规范里要求类型可替换和子签名,不是因为泛型擦除。
比如下面的例子就不是函数式接口:
最后,Java8里关于函数式接口的包是java.util.function,里面全部是函数式接口。主要包含几大类:Function、Predicate、Supplier、Consumer和*Operator(没有Operator接口,只有类似BinaryOperator这样的接口)。后面依次展开详细说明一下。
关于Function接口,其接口声明是一个函数式接口,其抽象表达函数为
函数意为将参数T传递给一个函数,返回R。即$R=Function(T)$
其默认实现了3个default方法,分别是compose、andThen和identity,对应的函数表达为:compose对应$V=Function(ParamFunction(T))$,体现嵌套关系;andThen对应$V=ParamFunction(Function(T))$,转换了嵌套的顺序;还有identity对应了一个传递自身的函数调用对应$Function(T)=T$。从这里看出来,compose和andThen对于两个函数f和g来说,f.compose(g)等价于g.andThen(f)。看个例子:
只是普通的lambda表达式,其能力有限。我们会希望引入更强大的函数能力——高阶函数,可以定义任意同类计算的函数。
比如这个函数定义,参数是z,返回值是一个Function,这个Function本身又接受另一个参数y,返回z+y。于是我们可以根据这个函数,定义任意加法函数:
由于高阶函数接受一个函数作为参数,结果返回另一个函数,所以是典型的函数到函数的映射。
BiFunction提供了二元函数的一个接口声明,举例来说:
其输出结果将是:f(z)=x*y, when x=3,y=5, then f(z)=15。
二元函数没有compose能力,只是默认实现了andThen。
有了一元和二元函数,那么可以通过组合扩展出更多的函数可能。
Function接口相关的接口包括:
BiFunction :R apply(T t, U u);接受两个参数,返回一个值,代表一个二元函数;
DoubleFunction :R apply(double value);只处理double类型的一元函数;
IntFunction :R apply(int value);只处理int参数的一元函数;
LongFunction :R apply(long value);只处理long参数的一元函数;
ToDoubleFunction:double applyAsDouble(T value);返回double的一元函数;
ToDoubleBiFunction:double applyAsDouble(T t, U u);返回double的二元函数;
ToIntFunction:int applyAsInt(T value);返回int的一元函数;
ToIntBiFunction:int applyAsInt(T t, U u);返回int的二元函数;
ToLongFunction:long applyAsLong(T value);返回long的一元函数;
ToLongBiFunction:long applyAsLong(T t, U u);返回long的二元函数;
DoubleToIntFunction:int applyAsInt(double value);接受double返回int的一元函数;
DoubleToLongFunction:long applyAsLong(double value);接受double返回long的一元函数;
IntToDoubleFunction:double applyAsDouble(int value);接受int返回double的一元函数;
IntToLongFunction:long applyAsLong(int value);接受int返回long的一元函数;
LongToDoubleFunction:double applyAsDouble(long value);接受long返回double的一元函数;
LongToIntFunction:int applyAsInt(long value);接受long返回int的一元函数;
Operator其实就是Function,函数有时候也叫作算子。算子在Java8中接口描述更像是函数的补充,和上面的很多类型映射型函数类似。
算子Operator包括:UnaryOperator和BinaryOperator。分别对应单元算子和二元算子。
算子的接口声明如下:
二元算子的声明:
很明显,算子就是一个针对同类型输入输出的一个映射。在此接口下,只需声明一个泛型参数T即可。对应上面的例子:
例子里补充一点的是,BinaryOperator提供了两个默认的static快捷实现,帮助实现二元函数min(x,y)和max(x,y),使用时注意的是排序器可别传反了:)
其他的Operator接口:(不解释了)
LongUnaryOperator:long applyAsLong(long operand);
IntUnaryOperator:int applyAsInt(int operand);
DoubleUnaryOperator:double applyAsDouble(double operand);
DoubleBinaryOperator:double applyAsDouble(double left, double right);
IntBinaryOperator:int applyAsInt(int left, int right);
LongBinaryOperator:long applyAsLong(long left, long right);
predicate是一个谓词函数,主要作为一个谓词演算推导真假值存在,其意义在于帮助开发一些返回bool值的Function。本质上也是一个单元函数接口,其抽象方法test接受一个泛型参数T,返回一个boolean值。等价于一个Function的boolean型返回值的子集。
其默认方法也封装了and、or和negate逻辑。写个小例子看看:
Predicate在Stream中有应用,Stream的filter方法就是接受Predicate作为入参的。这个具体在后面使用Stream的时候再分析深入。
其他Predicate接口:
BiPredicate:boolean test(T t, U u);接受两个参数的二元谓词
DoublePredicate:boolean test(double value);入参为double的谓词函数
IntPredicate:boolean test(int value);入参为int的谓词函数
LongPredicate:boolean test(long value);入参为long的谓词函数
看名字就可以想到,这像谓词函数接口一样,也是一个Function接口的特殊表达——接受一个泛型参数,不需要返回值的函数接口。
这个接口声明太重要了,对于一些纯粹consume型的函数,没有Consumer的定义真无法被Function家族的函数接口表达。因为Function一定需要一个泛型参数作为返回值类型(当然不排除你使用Function来定义,但是一直返回一个无用的值)。比如下面的例子,如果没有Consumer,类似的行为使用Function表达就一定需要一个返回值。
其他Consumer接口:
BiConsumer:void accept(T t, U u);接受两个参数
DoubleConsumer:void accept(double value);接受一个double参数
IntConsumer:void accept(int value);接受一个int参数
LongConsumer:void accept(long value);接受一个long参数
ObjDoubleConsumer:void accept(T t, double value);接受一个泛型参数一个double参数
ObjIntConsumer:void accept(T t, int value);接受一个泛型参数一个int参数
ObjLongConsumer:void accept(T t, long value);接受一个泛型参数一个long参数
最后说的是一个叫做Supplier的函数接口,其声明如下:
其简洁的声明,会让人以为不是函数。这个抽象方法的声明,同Consumer相反,是一个只声明了返回值,不需要参数的函数(这还叫函数?)。也就是说Supplier其实表达的不是从一个参数空间到结果空间的映射能力,而是表达一种生成能力,因为我们常见的场景中不止是要consume(Consumer)或者是简单的map(Function),还包括了new这个动作。而Supplier就表达了这种能力。
比如你要是返回一个常量,那可以使用类似的做法:
这保证supplier对象输出的一直是1。
如果是要利用构造函数的能力呢?就可以这样:
这样的输出可以看到,全部的对象都是new出来的。
这样的场景在Stream计算中会经常用到,具体在分析Java 8中Stream的时候再深入。
其他Supplier接口:
BooleanSupplier:boolean getAsBoolean();返回boolean
DoubleSupplier:double getAsDouble();返回double
IntSupplier:int getAsInt();返回int
LongSupplier:long getAsLong();返回long
整个函数式接口的大概总结如下:
ID:yunqiinsight
云计算丨互联网架构丨大数据丨机器学习丨运维
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
今日搜狐热点接口类型的定义类似于类的定义;接口定义的形式如下:;[修饰符]interface接口名[extend;像类那样,编译好的接口被保存在class文件中;interface前的修饰符是可选的;类;接口说明中的extends关键词和类说明中的ex;2.接口体就是用大括号括起来的那部分;例3.11接口的定义实例;像类一样,接口可以有两种成员:成员变量和成员方法;接口
接口类型的定义类似于类的定义。 接口定义的形式如下: [修饰符] interface 接口名 [extends] [接口列表] { 接口体 } 像类那样,编译好的接口被保存在class 文件中。 1.接口说明 interface 前的修饰符是可选的。当没有修饰符的时候,表示此接口的访问只限于同包的 类。如果使用修饰符,则只能用public 修饰符,表示此接口是公有的,在任何地方都可以引用它,这一点和类是相同的。 接口说明中的extends 关键词和类说明中的extends 一样,用来定义直接的父接口。和类不同,一个接口可以继承多个父接口,当extends 后面有多个父接口时,它们之间用逗号隔开,例如,下面是一个最简单的接口说明: public interface boy extends person, man
2. 接口体就是用大括号括起来的那部分。接口体说明接口的成员,包括常量和抽象方法。 例3.11 接口的定义实例。 interface boy { final int MAX=50; void increment( ); void decrement( ); int currentcount( ); } 像类一样,接口可以有两种成员:成员变量和成员方法。 (1)接口中的成员变量 接口中所有的成员变量都隐含的是public、static、final 的,因此接口中的成员变量都是静态最终变量。在接口中成员变量声明的形式如下: [修饰符] 类型名 变量名列表; 例如,在接口中有下面这行代码:“int i=5;”等同于:“public static final int i=5;”。 (2)接口中的方法 接口中说明的方法都是抽象方法,其声明的形式为 [修饰符] 方法返回值类型 方法名(参数列表); 由于接口中的方法都是抽象方法,所以方法体仅仅有一个分号“;”(连“{”和“}”都 没有)。修饰符可选,美国服务器租用商提醒您它只能是public 和abstract。接口中的所有方法都隐含的是public 和abstract 的,接口的方法不能是带static、final 等其他修饰符的。 3. 接口的实现 接口的声明仅仅给出了抽象方法,而具体地实现接口所定义的方法需要某个类为接口中 的每个抽象方法定义具体的操作。 在类的声明部分,用implements 关键字来声明这个类实现某个接口,一个类可以实现多个接口,在implements 子句中用逗号隔开。 如果实现某接口的类不是abstract 修饰的抽象类,则必须在类的定义部分实现指定接口 的所有抽象方法,即为所有抽象方法定义方法体,而且,方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表 如果实现某接口的类是abstract 修饰的抽象类,则它可以不实现该接口的所有方法。但是,在这个抽象类的任何一个非抽象的子类中,都必须有它们父类所实现的接口中的所有抽象方法实现的方法体。这些方法体可以来自抽象的父类,也可以来自子类自身。但是不允许存在未被实现的接口方法,这主要体现了非抽象类中不能存在抽象方法的原则。 一个类在实现某接口的抽象方法时,香港服务器租用商提醒您必须使用完全相同的方法头。如果所实现的方法与 抽象方法有相同的方法名和不同的参数列表,则只是在重载一个新方法,而不是实现已有的抽象方法。 接口的抽象方法的访问控制符都已被指定为叫public,所以类在实现这些抽象方法时,必须显式地使用public 修饰符,否则将被警告为缩小了接口中定义的方法的访问控制范围。 例3.12 接口实现实例。 interface interCalArea { double PI=3.14159; double cal(double r); } public class CalArea implements interCalArea { public double cal(double r) { return PI*r*r; } public static void main(String[] args) { CalArea CA=new CalArea(); System.out.println(\} } 程序运行结果如下: Area=452.94 程序中定义了一个接口interCalArea,该接口定义了一个常量PI 和方法cal( ),在类CalArea 中实现了cal( )方法,并在该方法中使用PI 计算圆的面积。在main( )方法中创建CalArea 类的实例CA,并调用CA 的cal( )方法计算圆的面积,最终显示出来。
三亿文库3y.uu456.com包含各类专业文献、各类资格考试、幼儿教育、小学教育、应用写作文书、高等教育、生活休闲娱乐、外语学习资料、Java接口中成员变量和成员方法的介绍93等内容。 
 Java 中成员变量又分为实例成员变量和___。 Java ...因为类体的内容由成员变量的定义和成员方法的定义两...接口中的方法被默认的访问权限是___。 如果接口中...  Java的对象、类、方法和接口_IT/计算机_专业资料。...在一个类中,成员变量的名字是唯一的,但成员变 量...但是,有时候方法体内部定义的变量和成员变量名字相同...  在 Java 中一个类不能同时继承一个类和实现一个接口 (D).Java 的单一继承使代码不可靠 25.实例可以操作类的( ) (A).成员变量 (B).成员方法 (C).A、...  两个成员方法名相同 C. 成员变量与成员方法名相同 D. 两个成员变量名相同 11...8、接口中能定义抽象方法和___常量___。 9、 在 Java 中, 所有的类都是...  54 Java 中成员变量又分为 实例成员变量 和类成员...69 因为类体的内容由成员变量的定义和成员方法的...127 接口中的方法被默认的访问权限是 public 。 ...  下面对 static 的描述错误的是 b A. 静态修饰的成员变量和成员方法随着类的...Java 接口中可以被多个子类实现,一个类也可以同时实现多个接口 C. Java 接口...  接口中的方法体可以由 Java 语言书写,也可以由其他语言书写,此时接口方法需要用...44. 说明类成员变量与实例成员变量的区别?有无 static 修饰,前者属于类,后者...  在 Java 接口中,下列选项中有效的方法声明是(AB)。(选择二项) A、public ...3. 变量属性是描述变量的作用域,按作用域分类,变量有局部变量、类变量、方法...他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)C++虚函数&与java&接口
什么是接口?
接口是包含一组虚方法的抽象类型,其中每一种方法都有其名称、参数和返回值。接口方法不能包含任何实现,CLR允许接口可以包含事件、属性、索引器、静态方法、静态字段、静态构造函数以及常数。但是注意:C#中不能包含任何静态成员。一个类可以实现多个接口,当一个类继承某个接口时,它不仅要实现该接口定义的所有方法,还要实现该接口从其他接口中继承的所有方法。
什么是抽象类?
抽象类提供多个派生类共享基类的公共定义,它既可以提供抽象方法,也可以提供非抽象方法。抽象类不能实例化,必须通过继承由派生类实现其抽象方法,因此对抽象类不能使用new关键字,也不能被密封。如果派生类没有实现所有的抽象方法,则该派生类也必须声明为抽象类。另外,实现抽象方法由overriding方法来实现。
都不能被直接实例化,都可以通过继承实现其抽象方法。
都是面向抽象编程的技术基础,实现了诸多的设计模式。
接口支持多继承;抽象类不能实现多继承。
接口只能定义抽象规则;抽象类既可以定义规则,还可能提供已实现的成员。
接口是一组行为规范;抽象类是一个不完全的类,着重族的概念。
接口可以用于支持回调;抽象类不能实现回调,因为继承不支持。
接口只包含方法、属性、索引器、事件的签名,但不能定义字段和包含实现的方法;抽象类可以定义字段、属性、包含有实现的方法。&
接口可以作用于值类型和引用类型;抽象类只能作用于引用类型。例如,Struct就可以继承接口,而不能继承类。
MSDN的建议是:
如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类,所有继承类都随更改自动更新。另一方面,接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。
如果创建的功能将在大范围的全异对象间使用,则使用接口。抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
如果要设计小而简练的功能块,则使用接口。如果要设计大的功能单元,则使用抽象类。
如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。抽象类允许部分实现类,而接口不包含任何成员的实现。
接口和抽象类,是论坛上、课堂间讨论最多的话题之一,之所以将这个老话题拿出来再议,是因为从我的体会来说,深刻的理解这两个面向对象的基本内容,对于盘活面向对象的抽象化编程思想至关重要。本文基本概况了接口和抽象类的概念、异同和使用规则,从学习的观点来看,我认为这些总结已经足以表达其核心。但是,对于面向对象和软件设计的深入理解,还是建立在不断实践的基础上,Scott说自己每天坚持一个小时用来写Demo,那么我们是不是更应该勤于键盘呢。对于接口和抽象类,请多用而知其然,多想而知其奥吧。
虚函数 & & --------
& 普通函数
纯虚函数 & -------- & 抽象函数
抽象类 & & --------
虚基类 & & --------
java 中没有多继承,但是可以通过接口、抽象类等技巧实现多继承。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 java 函数式接口 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信