300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > [解锁新姿势] 分享 7 个优化代码的技巧

[解锁新姿势] 分享 7 个优化代码的技巧

时间:2021-06-27 00:32:46

相关推荐

[解锁新姿势] 分享 7 个优化代码的技巧

点击上方IT牧场,选择置顶或者星标

技术干货每日送达

来源:https://juejin.im/post/6844903983744548877

前言

在我们平常开发过程中,由于项目时间紧张,代码可以用就好,往往会忽视代码的质量问题。甚至有些复制粘贴过来,不加以整理规范。往往导致项目后期难以维护,更别说后续接手项目的人。所以啊,我们要编写出优雅的代码,方便你我他,岂不美哉?

下面分享一些我在开发中常用的编码中小建议,如有不妥,欢迎大家一起交流学习。

卫语句

卫语句,就是把复杂的条件表达式拆分成多个条件表达式。比如 多个if-elseif-else嵌套, 可以拆分成多个if。如下面代码

代码:

--------------------before--------------------publicvoidtoday(){if(isWeekend()){if(isFee()){System.out.println("studyAndroid");}else{System.out.println("playagame");}}else{System.out.println("gotowork");}}--------------------after(建议)--------------------publicvoidtoday(){//提前过滤掉`特殊情况`if(!isWeekend()){System.out.println("gotowork");return;//提前return}//提前过滤掉`特殊情况`if(isFee()){System.out.println("studyAndroid");return;//提前return}//更关注于`核心业务`代码实现。System.out.println("playagame");}

提前过滤掉特殊情况,更关注核心业务逻辑

小函数

我们平常开发的时候,应该编写小而美函数,避免函数过长。一般函数最好在15行以内(建议) 我们看看下面代码:

--------------------before--------------------if(age>0&&age<18){System.out.println("小孩子");}if(number.length()==11){System.out.println("符合手机号");}--------------------after(建议)--------------------privatestaticbooleanisChild(intage){returnage>0&&age<18;}privatestaticbooleanisPhoneNumber(Stringnumber){returnnumber.length()==11;}if(isChild(age)){System.out.println("小孩子");}if(isPhoneNumber(number)){System.out.println("符合手机号");}复制代码

把判断语句抽取成一个个小函数, 这样代码更加清晰明了。

迪米特法则

概念:

迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少了解。例如 当一条语句中 一个对象出现两个.student.getName().equals("张三")) 就是代码坏味道的表现,如下代码所示。

代码:

--------------------before--------------------publicclassStudent{privateStringname;publicStudent(Stringname){this.name=name;}publicStringgetName(){returnname;}}publicstaticvoidmain(String[]args){Studentstudent=newStudent("张三");//注意看这里,//这里获取student的name属性,在根据name属性进行判断if(StringUtils.isNotBlank(student.getName())&&student.getName().equals("张三")){System.out.println("我的好朋友是"+student.getName());}}--------------------after(建议)--------------------publicclassStudent{...省略name代码//新增一个判断是否是我的好朋友方法publicbooleanisGoodFriend(){returnStringUtils.isNotBlank(this.name)&&this.name.equals("张三");}}publicstaticvoidmain(String[]args){Studentstudent=newStudent("张三");//根据迪米特法则,把判断逻辑,抽取到Student内部,暴露出方法(isGoodFriend)if(student.isGoodFriend()){System.out.println("我的好朋友是"+student.getName());}}

IDEA/Android Studio 抽取方法快捷键:option + command + M

Map 提取对象

我们在平常开发中,会使用到map,但是在面向对象开发理念中,一个map的使用,往往就会错过了Java Bean。建议使用Java Bean更直观。如下代码:

publicstaticvoidmain(String[]args){--------------------before--------------------Map<String,String>studentMap=newHashMap<>();studentMap.put("张三","男");studentMap.put("小红","女");studentMap.put("李四","男");studentMap.forEach((name,sex)->{System.out.println(name+":"+sex);});--------------------after(建议)--------------------List<Student>students=newArrayList<>();students.add(newStudent("张三","男"));students.add(newStudent("小红","女"));students.add(newStudent("李四","男"));for(Studentstudent:students){System.out.println(student.getName()+":"+student.getSex());}}

笔者在编写这点时候,有所顾虑。肯定有小伙伴跳出来说,mapbean不是一样吗?用map我还可以省去思考如何命名Class呢。但是从代码规范来说,这样代码设计不是更符合Java 面向对象的思想吗?

Stream

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。使得代码调用起来更加优雅~ 直接来看代码:

publicstaticvoidmain(String[]args){List<Student>students=newArrayList<>();students.add(newStudent("张三","男"));students.add(newStudent("李四","男"));students.add(newStudent("小红","女"));students.add(newStudent("小花","女"));students.add(newStudent("小红","女"));--------------------before--------------------//统计男生个数//传统的foreach循环遍历longboyCount=0;for(Studentstudent:students){if(student.isBoy()){boyCount++;}}System.out.println("男生个数="+boyCount);--------------------after(建议)--------------------//统计男生个数//stream流遍历longcount=students.stream().filter(Student::isBoy)//等同于.filter(student->student.isBoy()).count();System.out.println("男生个数="+boyCount);}

相比与 传统的For循环,更推荐大家使用stream遍历。stream流的链式调用,还有许多骚操作,如sorted,map,collect等操作符,可以省去不必要if-elsecount等判断逻辑。

多态

Java 三大特性之一,多态,相信大家都不会陌生,多态的好处就是根据对象不同类型采取不同的的行为。我们常常在编写switch语句的时候,如果改用多态,可以把每个分支,抽取到一个子类内的覆写函数中,这就更加灵活。

我们有这样一个需求,编写一个简单计算器方法,我们先来看一小段代码:

--------------------before--------------------publicstaticintgetResult(intnumberA,intnumberB,Stringoperate){intresult=0;switch(operate){case"+":result=numberA+numberB;break;case"-":result=numberA-numberB;break;case"*":result=numberA*numberB;break;case"/":result=numberA/numberB;break;}returnresult;}--------------------after(建议)--------------------abstractclassOperate{abstractintcompute(intnumberA,intnumberB);}classAddOperateextendsOperate{@Overrideintcompute(intnumberA,intnumberB){//TODO在这里处理相关逻辑returnnumberA+numberB;}}...SubOperate,MulOperate,DivOperate也和AddOperate一样这里就不一一贴出publicstaticintgetResult(intnumberA,intnumberB,Stringoperate){intresult=0;switch(operate){case"+":result=newAddOperate().compute(numberA,numberB);break;case"-":result=newSubOperate().compute(numberA,numberB);break;case"*":result=newMulOperate().compute(numberA,numberB);break;case"/":result=newDivOperate().compute(numberA,numberB);break;}returnresult;}

有小伙伴可能会说,你这不是更复杂了吗?

对比起单纯的switch,我们可以这样理解:

虽然在类上有所增加,但是通过多态,把对应操作的逻辑分离出来,使得代码耦合度降低。

如果要修改对应加法的逻辑, 我们只需要修改对应AddOperate类就可以了。避免直接修改getResult方法

代码可读性更好,语义更加明确。

但是这里会存在一些问题,如果我们新增一个平方根平方等计算方式, 就需要修改switch里面的逻辑,新增一个条件分支。下面我们再来看看更进一步的优化。

反射

通过上面例子,我们可以进一步优化,通过反射生成对应的Class,然后在调用compute方法。如下代码:

publicstatic<TextendsOperate>intgetResult(intnumberA,intnumberB,Class<T>clz){intresult=0;try{returnclz.newInstance().compute(numberA,numberB);}catch(InstantiationException|IllegalAccessExceptione){e.printStackTrace();returnresult;}}publicstaticvoidmain(String[]args){//调用的时候直接传递class即可System.out.println(getResult(1,2,SumOpearte.class));}

根据传入class参数,然后生成对应Opearte处理类, 对比多态方式,我们这里采用反射,使得代码耦合度大大降低,如果在增加平方根平方等计算方式。我们只需要 新增一个class继承Opearte即可,getResult不用做任何修改。

需要注意的是,不是所有switch语句都需要这样替换, 在面对简单的switch语句,就不必要了, 避免过度设计的嫌疑。如下代码:

publicStringgetResult(inttypeCode){Stringtype="";switch(typeCode){case0:type="加法";break;case1:type="减法";break;case2:type="乘法";break;case3:type="除法";break;}returntype;}

干货分享

最近将个人学习笔记整理成册,使用PDF分享。关注我,回复如下代码,即可获得百度盘地址,无套路领取!

•001:《Java并发与高并发解决方案》学习笔记;•002:《深入JVM内核——原理、诊断与优化》学习笔记;•003:《Java面试宝典》•004:《Docker开源书》•005:《Kubernetes开源书》•006:《DDD速成(领域驱动设计速成)》•007:全部•008:加技术群讨论

近期热文

•LinkedBlockingQueue vs ConcurrentLinkedQueue•解读Java 8 中为并发而生的 ConcurrentHashMap•Redis性能监控指标汇总•最全的DevOps工具集合,再也不怕选型了!•微服务架构下,解决数据库跨库查询的一些思路•聊聊大厂面试官必问的 MySQL 锁机制

关注我

喜欢就点个"在看"呗^_^

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。