那些不够优雅的java代码片段(一)

3,222 阅读5分钟
原文链接: blog.csdn.net

我觉得严谨对于每个程序员来说都至关重要,而写出优雅而又高效的代码是我们毕生所求。

前言

可能是处女座的原因,我对代码要求很高,我组内几位开发的代码提交前我都会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 = list.size() - 1; i >= 0; i--) {
            if ("邵磊".equals(list.get(i).getName())) {
                user=list.get(i);
            }
        }

改为

        for (int i = list.size() - 1; i >= 0; i--) {
            if ("邵磊".equals(list.get(i).getName())) {
                user=list.get(i);
                break;
            }
        }

假设除某个姓名的人,不执行某些操作,代码如下:

        for (int i = list.size() - 1; i >= 0; i--) {
            if ("邵磊".equals(list.get(i).getName())) {
                //这里只有2件事。
                user=list.get(i);
            }else{
                //这里做很多事情
            }
        }

这时,我们可以去掉if,并使用continue

        for (int i = list.size() - 1; i >= 0; i--) {
            if ("邵磊".equals(list.get(i).getName())) {
                //这里只有2件事。
                user=list.get(i);
                continue;
            }
            //这里做很多事情
        }

continue:跳出本次循环继续下一次循环
break: 跳出循环体,继续执行循环外的函数体
return: 跳出整个函数体,函数体后面的部分不再执行

对for循环不熟

        if (list.size()==0) {
            for (int i = list.size() - 1; i >= 0; i--) {
                //做事情
            }
        }

而我们知道即使list.size()==0也不会影响代码,不如直接

        for (int i = list.size() - 1; i >= 0; i--) {
            //做事情
        }

错用try catch

try catch包裹一大块

        try {
            //这段代码可能异常
            //下面代码不会异常
            //此处代码不会异常
            //此处代码不会异常
        } catch (Exception e) {
            //报错
        }

不如改为

        try {
            //这段代码可能异常
        } catch (Exception e) {
            //报错
        }
        //下面代码不会异常
        //此处代码不会异常
        //此处代码不会异常

这样可读性更高,更优雅,当然了,也可以使用throws来捕获异常。 try catch写在for循环里

    for (int i = list.size() - 1; i >= 0; 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 7及以上,支持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;
for (int i = 1; i <= 100; i++)
{
    obj = new Object();
    //其他代码
}

总结

我们解决问题,可能有很多种思路,也能写出很多种代码来,但是把代码写的优雅却是一个技术活,当然了,本次先介绍部分,关注度高的话,我继续更新。 最后,我想补充一句,其实我不是处女座,只是别人会这么说我,所以我认了。

觉得好的话,记得关注我哦!
掘金:
juejin.cn/user/272334…