文章13 | 阅读 4723 | 点赞0
如果你还不熟悉java8的新特性,可以看下下面这篇文章 或者 B站红康师傅讲解的java8新特性,宋红康老师讲的不止有java8哦,乃至java 9-15的新特性都有,可以在B站中找到,或者尚硅谷官网可以免费获取到。
《B站尚硅谷官方运营号地址》
如果此前已经掌握了java8的新特性,至少lambda表达式是没啥大问题的。
要求设计一个计算器,其功能是完成两个数的四则运算(加减乘除)。
例如:有两个操作数 a 和 b 都是double类型的。
下面代码看起来没有问题,很nice 对吧。
public class Demo {
public static void main(String[] args) {
double a = 12, b = 3, result = 0;
result = Calculator.run("+", a, b);
System.out.println("加法 a + b = "+result); // 调用工具类得到结果
result = Calculator.run("-", a, b);
System.out.println("减法 a - b = "+result);
result = Calculator.run("*", a, b);
System.out.println("乘法 a * b = "+result);
result = Calculator.run("/", a, b);
System.out.println("除法 a / b = "+result);
}
}
/** * 封装的一个工具类 */
class Calculator {
/** * @param operatorString 运算符 * @param a 操作数1 * @param b 操作数2 * @return a,b经过运算符的结果值 */
public static double run(String operatorString, double a, double b) {
if (operatorString.equals("+")) {
return a + b;
} else if (operatorString.equals("-")) {
return a - b;
} else if (operatorString.equals("*")) {
return a * b;
} else if (operatorString.equals("/")) {
return a / b;
} else {
throw new IllegalArgumentException("非法操作符:" + operatorString);
}
}
}
如果你有一些工作经验了,你会发现像这种if-else
的写法很不好,看起来很不舒服。或许你会想到用switch
进行代替,但依然还是不舒服,因为写在一起,很容易看错,稍微不注意你就会因为这个if-else
埋坑。出现bug就很不好改
如果你之前看过我另外一篇文章,利用enmn
代替if-else
用枚举代替if-else的参考写法
import java.util.HashMap;
import java.util.Map;
public class EnmuMode {
private final static Map<String, String> map;
static {
map = new HashMap<>();
map.put("+", "ADD");
map.put("-", "SUBTRACT");
map.put("*", "MULTIPLY");
map.put("/", "DIVIDION");
}
public static void main(String[] args) {
double a = 12, b = 3, result = 0;
String option= "*"; // 运算操作
String strategy = map.getOrDefault(option, "EXCEPTION");// 得到策略字符串
result = CalculateEnum .valueOf(strategy).calculate(leftNum, rightNum);// 根据策略调用得到对应枚举,调用对应的方法得到计算的结果
System.out.println(result); // 打印计算后的结果
}
}
enum CalculateEnum {
ADD {
@Override
public double calculate(double leftNum, double rightNum) {
return leftNum + rightNum;
}
},
SUBTRACT {
@Override
public double calculate(double leftNum, double rightNum) {
return leftNum - rightNum;
}
},
MULTIPLY {
@Override
public double calculate(double leftNum, int rightNum) {
return leftNum * rightNum;
}
},
DIVIDION {
@Override
public double calculate(double leftNum, double rightNum) {
return leftNum / rightNum;
}
},
EXCEPTION {
@Override
public double calculate(double leftNum, double rightNum) {
throw new IllegalArgumentException("运算操作不支持");
}
};
/** * 将操作数 leftNum,rightNum 运算得到新值 * return 计算后的结果值 */
double calculate(double leftNum, double rightNum);
}
定义一个函数式接口,使用lambda表达式完成功能
public class JAVA8Demo {
public static void main(String[] args) {
CalculateImpl calculate = new CalculateImpl(); // 得到计算器的实现类
double a = 12, b = 3;
double result = calculate.test((x, y) -> x + y, a, b);
System.out.println("加法 a+b=" + result);
double result2 = calculate.test((x, y) -> x - y, a, b);
System.out.println("减法 a-b=" + result2);
double result3 = calculate.test((x, y) -> x * y, a, b);
System.out.println("乘法 a*b=" + result3);
double result4 = calculate.test((x, y) -> x / y, a, b);
System.out.println("除法 a/b=" + result4);
}
}
/** * 封装接口类,用于进行java8的数据流传递 */
class CalculateImpl {
public double test(Calculate calculate, double a, double b) {
return calculate.run(a, b); // 将计算后的结果值直接返回
}
}
/*定义一个函数式接口*/
interface Calculate {
/** * 调用方法得到a,b的结果值 */
double run(double a, double b);
}
利用 java8 已经提供好的一些常用接口代替自己定义的接口Calculate
public class JAVA8Demo {
public static void main(String[] args) {
CalculateImpl calculate = new CalculateImpl();
double a = 12, b = 3;
double result = calculate.test((x, y) -> x + y, a, b);
System.out.println("加法 a+b=" + result);
double result2 = calculate.test((x, y) -> x - y, a, b);
System.out.println("减法 a-b=" + result2);
double result3 = calculate.test((x, y) -> x * y, a, b);
System.out.println("乘法 a*b=" + result3);
double result4 = calculate.test((x, y) -> x / y, a, b);
System.out.println("除法 a/b=" + result4);
}
}
class CalculateImpl {
public double test(BiFunction<Double,Double,Double> biFunction, double a, double b) {
return biFunction.apply(a, b);
}
}
第一种写法,设计简单,通过传入操作符来判断使用那种运算,通过封装,将if-else
封装好,但缺点也比较明显,if-else
导致代码的可阅读性变差。而且高度耦合。如果要增加求余数等其它运算操作就得直接修改if-else
分支源码,如果功能特别多,那么这个if-else
就特别长,看都不想看的那种。
第二种写法,利用枚举代替if-else
,这种写法会比if-else
的代码阅读性会好一些,这些功能通过构造器被拆分出来,如果也要增加新功能,那么需要增加枚举的构造器,实现抽象方法来完成功能。优点是可以在其它类中复用代码,缺点就也是需要修改源码,具有一定的耦合性,但比第一种好。
第三种写法,利用函数式编程的思想,设计了一个接口,利用接口将计算后的结果值返回,为了进一步的优化,利用CalculateImpl.test()
方法将接口进一步封装,而接口的实现则由lambda
表达式完成。从代码量看出,这种写法的代码是最少的,也意味着java8的代码产出量是最大的。与写法一、写法二相比更具可变性,想要增加什么功能就能增加什么功能,缺点就是代码不容易复用,使用lambda表达式增加的功能不好在其它类中复用。也就是不能同对象.
调用对应方法完成对应功能。
第四种写法,是熟悉java8源码的程序员才会的写法,没看过源码或者没见过这种写法的是不会想到这样写。
第四种写法引发了一个问题,你熟悉java8的源码?你知道java8提供了哪些常用函数式接口吗?
文章末尾,希望这次案例能引发大家对源码的学习兴趣,要想写出好程序,是要熟悉jdk源码的。
如果你对jdk源码也很感兴趣。可以在我的 jdk源码专栏 或者 juc 专栏中找到一些我对jdk源码的阅读和对于源码的理解的相关文章。我欢迎大家的评论和指教,文章中如有错误的地方请指出,我会改正过来。
如果你喜欢这类文章,可以点个关注,我写博客的频率是比较高的,说不定有很多好文章在等着我们一起学习学习。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://yumbo.blog.csdn.net/article/details/110791665
内容来源于网络,如有侵权,请联系作者删除!