java静态引用_Java开发中静态方法引用和实例方法引用案例详细讲解

a1d00cd145a80103a921e337cbcc57d3.pngJava开发

前言

在Java的日常开发中静态方法引用和实例方法引用在很多地方都会用到,可以说是万金油,但是你真的掌握了吗?下面就由小编给大家做一个比较细想的讲解,废话不多说现在开始把。

正文

大家对于方法引用的概念及其业务场景都已经非常熟悉了,但是被引用的方法必须属于外层匿名方法(即Lambda表达式)的数据类型,像isEmpty、contains、startsWith、endsWith、matches、compareTo、compareToIgnoreCase等等无一例外全部归属String字符串类型,假使Lambda表达式输入参数的数据类型并不拥有式子右边的方法,那么方法引用还能派上用场吗?当然Java8憋出方法引用这么一个大招,绝非只想让它走过场而已,而是要除旧革新深入应用。其实仅仅涉及到方法引用的其中一个分支——参数方法引用,该分支顾名思义被引用的方法对应于入参的数据类型。方法引用还有其它两个分支,分别是静态方法引用和实例方法引用,接下来依次进行详细说明。  首先是静态方法引用,所谓静态表示被引用的方法乃某个工具类的静态方法。为了逐步展开相关论述,开头还是先定义一个专属的计算器接口,同时该接口也是一个标准的函数式接口。下面是计算器接口的定义代码:

//定义一个计算器接口,给算术类使用public interface Calculator {// 声明一个名叫运算的抽象方法 public double operate(double x, double y);}

可见计算器接口声明了一个运算方法,该方法有两个浮点入参。之所以把运算方法当作抽象类型,是为了支持动态指定两个数字的运算操作,例如可以对这两个数字进行相加运算,或者相乘运算,或者求两数的最大值,或者求两数的最小值等等。为此还要定义一个算术工具类,在该工具类中编写calculate方法,将计算器接口以及两个操作数作为calculate方法的输入参数。这个算术工具类的角色相当于数组工具类Arrays,它的定义代码示例如下:

//定义一个算术类public class Arithmetic {// 定义一个静态的计算方法,根据传入的计算器接口,对后面两个数字进行运算 public static double calculate(Calculator calculator, double x, double y) { // 这里调用了计算器接口的运算方法 return calculator.operate(x, y); }}

现在轮到外部去调用算术类Arithmetic,倘若命令计算器去求两个数字的较大值,则参照Arrays工具的sort方法格式,可编写如下所示的运算代码(包括匿名内部类方式与Lambda表达式):

// 演示静态方法的方法引用private static void testStatic() {double result; // 采取匿名内部类方式对两个操作数进行指定运算(求较大值) result = Arithmetic.calculate(new Calculator() { @Override public double operate(double x, double y) { return Math.max(x, y); } }, 3, 2); // 采取Lambda表达式对两个操作数进行指定运算(求较大值) result = Arithmetic.calculate((x, y) -> Math.max(x, y), 3, 2);}

显然求最大值用到的max方法属于Math数学函数库,不属于x与y二者的变量类型,并且max还是Math工具的静态方法而非实例方法。尽管此时max方法不符合参数方法引用,但它恰恰跟静态方法引用对上号了,因而Lambda表达式“(x, y) -> Math.max(x, y)”允许简写为“Math::max”。以此类推,通过Arithmetic工具的calculate方法求两个数字的较小值,也能代入方法引用“Math::min”;求某个数字的n次方,可代入方法引用“Math::pow”;求两个数字之和,可代入方法引用“Double::sum”。于是在算术工具中运用静态方法引用的代码变成了下面这样:

// 采取双冒号的方法引用来替换Lambda表达式中的静态方法,求两数的较大值result = Arithmetic.calculate(Math::max, 3, 2);System.out.println("两数的较大值="+result);// 被引用的方法换成了Math.min,求两数的较小值result = Arithmetic.calculate(Math::min, 3, 2);System.out.println("两数的较小值="+result);// 被引用的方法换成了Math.pow,求某数的n次方result = Arithmetic.calculate(Math::pow, 3, 2);System.out.println("两数之乘方="+result);// 被引用的方法换成了Double.sum,求两数之和result = Arithmetic.calculate(Double::sum, 3, 2);System.out.println("两数之和="+result);

运行上述的计算代码,输出两个数字的各项运算结果见下:

两数的较大值=3.0两数的较小值=2.0两数之乘方=9.0两数之和=5.0

要是接着求两个数字之差、两个数字之积等等,就会发现不管是Math工具,还是包装浮点型Double,它们都没有可用的静态方法了。不过这难不倒我们,即使系统不提供,咱也能自己定义相应的计算方法呗。说时迟那时快,熟练的程序员早早准备好了包括常见运算在内的数学工具类,不但有四则运算,还有乘方和开方运算,完整的工具类代码如下所示:

//定义数学工具类public class MathUtil {// 加法运算 public double add(double x, double y) { return x+y; } // 减法运算 public double minus(double x, double y) { return x-y; } // 乘法运算 public double multiply(double x, double y) { return x*y; } // 除法运算 public double divide(double x, double y) { return x/y; } // 取余数运算 public double remainder(double x, double y) { return x%y; } // 取两数的较大值 public double max(double x, double y) { return Math.max(x, y); } // 取两数的较小值 public double min(double x, double y) { return Math.min(x, y); } // 幂运算,即乘方 public double pow(double x, double y) { return Math.pow(x, y); } // 求方根运算,即开方 public double sqrt(double x, double y) { double number = x; // 需要求n次方根的数字 double root = x; // 每次迭代后的数值 double n = y; // n次方根的n // 下面利用牛顿迭代法求n次方根 for (int i=0; i<5; i++) { root = (root*(n-1)+number/Math.pow(root, n-1))/n; } return root; }}

注意到MathUtil的内部方法全部是实例方法,而非静态方法,意味着外部若想调用这些方法,得先创建MathUtil的实例才行。比如下面这般:

MathUtil math = new MathUtil();

有了MathUtil类的实例之后,外部即可通过“math::add”表示相加运算的方法引用,通过“math::minus”表示相减运算的方法引用了。现今这种“实例名称::方法名称”的引用形式,正是方法引用的第三个分支——实例方法引用。下面的运算代码便演示了实例方法引用的具体用法:

// 演示实例方法的方法引用 private static void testInstance() { MathUtil math = new MathUtil(); double result; // 双冒号的方法引用也适用于实例方法,求两数之和 result = Arithmetic.calculate(math::add, 3, 2); System.out.println("两数之和="+result); // 被引用的方法换成了该实例的minus方法,求两数之差 result = Arithmetic.calculate(math::minus, 3, 2); System.out.println("两数之差="+result); // 被引用的方法换成了该实例的multiply方法,求两数之积 result = Arithmetic.calculate(math::multiply, 3, 2); System.out.println("两数之积="+result); // 被引用的方法换成了该实例的divide方法,求两数之商 result = Arithmetic.calculate(math::divide, 3, 2); System.out.println("两数之商="+result); // 被引用的方法换成了该实例的remainder方法,求两数之余 result = Arithmetic.calculate(math::remainder, 3, 2); System.out.println("两数之余="+result); // 被引用的方法换成了该实例的max方法,求两数的较大值 result = Arithmetic.calculate(math::max, 3, 2); System.out.println("两数的较大值="+result); // 被引用的方法换成了该实例的min方法,求两数的较小值 result = Arithmetic.calculate(math::min, 3, 2); System.out.println("两数的较小值="+result); // 被引用的方法换成了该实例的pow方法,求某数的n次方 result = Arithmetic.calculate(math::pow, 3, 2); System.out.println("两数之乘方="+result); // 被引用的方法换成了该实例的sqrt方法,求某数的n次方根 result = Arithmetic.calculate(math::sqrt, 3, 2); System.out.println("两数之开方="+result);}

运行如上的计算代码,可得到下列的计算结果日志:

两数之和=5.0  两数之差=1.0  两数之积=6.0  两数之商=1.5  两数之余=1.0  两数的较大值=3.0  两数的较小值=2.0  两数之乘方=9.0  两数之开方=1.7320508075688772

结尾

当然了,对于算术运算这茬事,本来就没有必要非得去创建实例,完全可以将add、minus、multiply等等诸多方法声明为静态方法,然后外部通过“MathUtil::add”、“MathUtil::minus”、“MathUtil::multiply”来引用对应方法。进行如此变更的唯一代价,便是把实例方法引用改成了静态方法引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值