我觉得严谨对于每个程序员来说都至关重要,而写出优雅而又高效的代码是我们毕生所求。
前言
可能是处女座的原因,我对代码要求很高,我组内几位开发的代码提交前我都会review一次,两年里,我pass掉了很多不满意的代码片段,有实习生写的,也有多年开发经验的同事写的。今天,突然心血来潮和大家分享一些代码片段,希望能给大家带来一些启发和灵感。
主题
受限于我们定式思维的影响,我们写出的代码,很多情况没有别人提醒,自己很难发现一些不妥的地方。
对map掌握不牢
- Student student=new Student("邵磊");
- Map<String, Object> map3 = new HashMap<String, Object>();
- map3.put("k", "学院");
- map3.put("v", student.getCollogeName());
- resultlist.add( map3);
- Map<String, Object> map4 = new HashMap<String, Object>();
- map4.put("k", "专业");
- map4.put("v", student.getMajorName());
- resultlist.add( map4);
- Map<String, Object> map5 = new HashMap<String, Object>();
- map5.put("k", "班级");
- map5.put("v", student.getBjmc());
- resultlist.add(map5);
上述代码,一看就知道,这位开发很可能刚开始只是用一个map,发现list.add后所有的map都是最后一个。
起初代码大概如下
- Student student=new Student("邵磊");
- Map<String, Object> map = new HashMap<String, Object>();
- map.put("k", "学院");
- map.put("v", student.getCollogeName());
- resultlist.add( map3);
- map.put("k", "专业");
- map.put("v", student.getMajorName());
- resultlist.add( map);
这样的代码会导致map被覆盖,因为key相同导致。
那改为他的代码有什么问题吗?
主要是变量名的问题,比如按这样逻辑,你下次还需要map6,map7,map8吧,这种变量维护几次之后,删除,增加都是不优雅的,不妨改为:
- Student student=new Student("邵磊");
- Map<String, Object> map = new HashMap<String, Object>();
- map.put("k", "学院");
- map.put("v", student.getCollogeName());
- resultlist.add( map3);
- map = new HashMap<String, Object>();
- map.put("k", "专业");
- map.put("v", student.getMajorName());
- resultlist.add( map);
这样,每次new 了一个hashmap,就可以省去起名不优雅的问题了。
再想想,觉得map里加k,v两个key键有些不优雅,索性改为实体类。
- Student student = new Student("邵磊");
- resultlist.add(new MapKV("学院", student.getCollogeName()));
- resultlist.add(new MapKV("专业", student.getMajorName()));
而这个MapKV就不用介绍了,只有2个String k v。
对mybatis掌握不牢
- public interface QuestionDao {
- List < Question > getQuestionList();
- }
对应的map文件QuestionMapper.xml
- List < Question > questionList = QuestionDao.findBy(params);
- if (mexamQuestionList == null) {
- //抛异常
- }
而mybatis的dao层返回的list不可能为null,即使size()=0只会返回一个new List,所以无需判断list为null
对equals不熟
- if (user.get("sl").equals("邵磊")) {
- //一大堆代码
- }
很多人说,这个错误怎么可能有,如果前面为null会报错,但是,我全局搜索过之前的项目,难免能发现一两个,毕竟有历史遗留问题,实习生问题等。因为我们知道null不能.equals,改为:
- if ("邵磊".equals(user.get("sl"))) {
- //一大堆代码
- }
滥用toString
- user.get("sl").toString();
而一旦前面为null就报错,null不能有任何方法。
对return不熟
- public String getResult() {
- if ("条件") {
- //一大堆代码
- return "结果";
- } else {
- //一大堆代码
- return "结果";
- }
- }
既然有return了确定以下代码不走,就可以放心大胆放出来
- public String getResult() {
- if ("条件") {
- //一大堆代码
- return "结果";
- }
- //一大堆代码
- return "结果";
- }
不会使用continue,break、if过长
比如查找某个list中某个姓名,当查找到了,要及时的break,来节约cpu。
- for (int i = 0; i < list.size(); i++) {
- if ("邵磊".equals(list.get(i).getName())) {
- user = list.get(i);
- }
- }
改为
- for (int i = 0; i < list.size(); i++) {
- if ("邵磊".equals(list.get(i).getName())) {
- user = list.get(i);
- break;
- }
- }
假设除某个姓名的人,不执行某些操作,代码如下:
- for (int i = 0; i < list.size(); i++) {
- if ("邵磊".equals(list.get(i).getName())) {
- //这里只有2件事。
- user = list.get(i);
- } else {
- //这里做很多事情
- }
- }
这时,我们可以去掉if,并使用continue
- for (int i = 0; i < list.size(); i++) {
- if ("邵磊".equals(list.get(i).getName())) {
- //这里只有2件事。
- user = list.get(i);
- continue;
- }
- //这里做很多事情
- }
continue:跳出本次循环继续下一次循环
break: 跳出循环体,继续执行循环外的函数体
return: 跳出整个函数体,函数体后面的部分不再执行
对for循环不熟
- if (list.size() == 0) {
- for (int i = 0; i < list.size(); i++) {
- //做事情
- }
- }
而我们知道即使list.size()==0也不会影响代码,不如直接
- for (int i = 0; i < list.size(); i++) {
- //做事情
- }
错用try catch
try catch包裹一大块
- try {
- //这段代码可能异常
- //下面代码不会异常
- //此处代码不会异常
- //此处代码不会异常
- } catch(Exception e) {
- //报错
- }
不如改为
- try {
- //这段代码可能异常
- } catch (Exception e) {
- //报错
- }
- //下面代码不会异常
- //此处代码不会异常
- //此处代码不会异常
这样可读性更高,更优雅,当然了,也可以使用throws来捕获异常。
try catch写在for循环里
- for (int i = 0; i < list.size(); i++) {
- try {
- //这段代码可能异常
- } catch(Exception e) {
- //报错
- }
- //下面代码不会异常
- }
我们知道try catch 会把整段代码包裹起来执行,这是需要耗费资源的,频繁的trycatch,除特殊情况,否则可抽取出方法,把方法包裹起来即可。
重复代码片段
比如一个方法,在某个类里,多次调用,而只有部分变量不同,可以抽取出方法及变量,来使代码简洁
不使用case
- if(type==1){
- }else if(type==2){
- }else if(type==3){
- }else if(type==4){
- }
- …………
这样写下去会写很长的if,而我们知道使用case也可以解决string匹配问题,在java 8以上,支持case 字符串。
- switch(参数) {
- case 常量表达式1: break;
- case 常量表达式2: break;
- ...
- default: break;
- }
未采用懒加载
如
- String str = "邵磊";
- if (i == 1) {
- list.add(str);
- }
可改为
- if (i == 1) {
- String str = "邵磊";
- list.add(str);
- }
不断创建对象引用
- for (int i = 1; i <= 100; i++)
- {
- Object obj = new Object();
- //其他代码
- }
这样做,只会在内存里开辟很多Object对象的引用,可改为
- Object obj = new Object();
- for (int i = 1; i <= 100; i++)
- {
- obj = new Object();
- //其他代码
- }
总结
我们解决问题,可能有很多种思路,也能写出很多种代码来,但是把代码写的优雅却是一个技术活,当然了,本次先介绍部分,关注度高的话,我继续更新。
最后,我想补充一句,其实我不是处女座,只是别人会这么说我,所以我认了。