面向函数-Function
-Function泛型接口与方法的入口地址
耿祥义
主要内容 1.方法的入口地址 2.得到方法的入口地址 3. Function接口变量
链接(单击阅读阅文也可以下载源代码):
https://pan.baidu.com/s/1LuyB-Uk99piRhghJbROXEQ
提取码: hxkj
1.基本知识点,方法的入口地址
①对象调用实例方法
当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址,只有该类创建对象后,类中的实例方法才分配入口地址。
②类名调用类方法(static方法)
对于类中的类方法,在该类被加载到内存时,就分配了相应的入口地址,类方法可以直接通过类名调用。
2.得到方法的入口地址
JDK8之后,可以类名使用“::”运算符得到该类的静态方法(static方法 )的入口地址,
类名::静态方法
其值的类型属于Function类型。
对象使用“::”运算符得到该类的实例方法的入口地址:
对象::实例方法
其值的类型属于Function类型。
比如,Math类的sqrt方法是static方法,那么
Math::sqrt
就是static方法sqrt的入口地址。
对于String str = new String("ABCD");
str::indexOf
就是实例方法indexOf方法的入口地址。
3 Function接口(在java.util.function包)变量
① Function类型
“::”运算符得到方法的入口地址类型是Function类型,因此“::”运算符得到方法的入口地址可以存放到Function接口变量中,例如:
Function funOne = Integer::parseInt;
Function funTwo = Math::sqrt;
Function接口变量声明变量时必须指定泛型T,R代表的具体类型,而且必须和::给出的方法的参数类型和返回类型相匹配。其中T替换成方法的参数类型,R替换成方法的返回类型。int parseInt(String)的参数类型是String类型(用String替换T),返回类型是int(用Integer替换R)。double sqrt(double)参数类型是double类型(用Double替换T),返回类型是double(用Double替换R)。
② R apply(T) 方法
“::”运算符将入口地址放入Function接口变量后,接口变量通过调用apply(T)来使用::”指定的方法,例如
funOne.apply("456") ;
相当于
Integer.parseInt("456");
注 如果方法是2个参数的请参阅Interface BiFunction接口即可。
4.例子1
下列例子1展示了 Function接口的基本用法。
import java.util.function.Function;
public class E1 {
public static void main(String args[]) {
Function funOne = Integer::parseInt;
System.out.println(""+funOne);
Integer m = funOne.apply("456") ;
System.out.println(m);
Function funTwo = Math::sqrt;
Double d = funTwo.apply(81.0) ;
System.out.println(d);
funTwo = Math::cos;
d = funTwo.apply(3.1415926) ;
System.out.println(d);
}
}
5.面向函数
教材在第5章5.10,讲授了面向抽象的思想。给出的例子,即设计的Pillar类满足开闭原理(柱体计算体积只关心底的面积不必关心它的类型),即系统在增加新的模块时,不需要修改Pillar类的代码。
在这里,例子2中的Pillar类
面向“函数”,即面向Function接口
(面向接口编程的特例)。当系统在增加新的模块时,比如Triangle类负责计算三角形面积,系统不必修改Pillar类。
在某些特殊情况下:方法是一个参数或无参数,系统某个类仅仅依赖方法的返回值,那么就可以面向函数编写该类,使得代码更加简练,
而且还可动态地传递Lambada表达式的值
(Lambada表达式的值是方法的入口地址)给Function接口。例子2中的Pillar面向“函数”,即Function接口。
例子2
Pillar.java
import java.util.function.Function;
public class Pillar{
double height;
Function bottom;
//面向“函数”
double getVolume(){
double v= bottom.apply(null)*height;
return v;
}
public void setHeight(double height){
this.height =height;
}
public void setBottom(Function fun){
bottom = fun;
}
}
E2.java
import java.util.function.Function;
public class E2 {
public static void main(String args[]) {
Pillar pillar = new Pillar();
Rect rect = new Rect();
rect.a = 100;
rect.b = 200;
pillar.setHeight(10);
pillar.setBottom(rect::getArea);
double volume=pillar.getVolume();
System.out.println(volume);
Circle circle = new Circle();
circle.r = 100;
pillar.setHeight(19.9);
pillar.setBottom(circle::getArea);
volume=pillar.getVolume();
System.out.println(volume);
pillar.setBottom((Void)->{ return 2020.0;});//传递Lambada表达式的值
volume=pillar.getVolume();
System.out.println(volume);
}
}
Rect.java
public class Rect{
double a,b;
public double getArea(Void v){
return a*b;
}
}
Circle.java
public class Circle{
double r;
public double getArea(Void v){
return Math.PI*r*r;
}
}