java一个式子开根号语句_Java代码优化小妙招「含代码示范」,让你的代码更整洁高效

小编今天突然发现,网上的程序员朋友们对2020年的评价褒贬不一,有点人说不是什么善年,也有人说是程序员的本命年。具体逻辑都是源自于一个式子2020-1024=996!!!前端时间在程序员圈子里很火的一个GitHub就叫工作996.ICU。而1024是程序员节。这两个数字组起来就是今年的日期。也是让小编觉得好巧啊,究竟是谁闲的没事干琢磨这个哈哈哈哈,不罗嗦了,让我们进入正文题

bcbe9f1baee9d171aa0f4b19b372d2f9.png

前言

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

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

卫语句

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

代码:

-------------------- before  --------------------public void today() {    if (isWeekend()) {        if (isFee()) {            System.out.println("study Android");        } else {            System.out.println("play a game");        }    } else {        System.out.println("go to work");    }} -------------------- after  (建议) --------------------public void today() {    // 提前过滤掉`特殊情况`    if (!isWeekend()) {        System.out.println("go to work");        return; // 提前return    }    //提前过滤掉`特殊情况`    if (isFee()) {        System.out.println("study Android");        return; // 提前return    }    // 更关注于 `核心业务`代码实现。    System.out.println("play a game");}

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

小函数

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

-------------------- before  --------------------if (age > 0 && age < 18){    System.out.println("小孩子");}if (number.length() == 11){    System.out.println("符合手机号");}-------------------- after (建议) --------------------private static boolean isChild(int age) {    return age > 0 && age < 18;}private static boolean isPhoneNumber(String number) {    return number.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  --------------------public class Student {    private String name;    public Student(String name) {        this.name = name;    }    public String getName() {        return name;    }}public static void main(String[] args) {    Student student = new Student("张三");    // 注意看这里,    // 这里获取 student的name属性,在根据name属性进行判断    if (StringUtils.isNotBlank(student.getName()) && student.getName().equals("张三")) {        System.out.println("我的好朋友是 " + student.getName());    }} -------------------- after (建议) --------------------  public class Student {    ... 省略name代码    // 新增一个 判断是否是我的好朋友方法    public boolean isGoodFriend(){        return StringUtils.isNotBlank(this.name) && this.name.equals("张三");    }}public static void main(String[] args) {    Student student = new Student("张三");    // 根据迪米特法则,把判断逻辑,抽取到 Student 内部,暴露出方法(isGoodFriend)    if (student.isGoodFriend()){        System.out.println("我的好朋友是 " + student.getName());    }}

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

Map 提取对象

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

public static void main(String[] args) {    -------------------- before  --------------------        Map studentMap = new HashMap<>();        studentMap.put("张三", "男");        studentMap.put("小红", "女");        studentMap.put("李四", "男");        studentMap.forEach((name, sex) -> {            System.out.println(name + " : " + sex);        });    -------------------- after (建议)  --------------------            List students = new ArrayList<>();        students.add(new Student("张三", "男"));        students.add(new Student("小红", "女"));        students.add(new Student("李四", "男"));        for (Student student : students) {            System.out.println(student.getName() + ":" + student.getSex());        }    }

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

Stream

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

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

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

多态

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

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

    -------------------- before  --------------------    public static int getResult(int numberA, int numberB, String operate) {        int result = 0;        switch (operate) {            case "+":                result = numberA + numberB;                break;            case "-":                result = numberA - numberB;                break;            case "*":                result = numberA * numberB;                break;            case "/":                result = numberA / numberB;                break;        }        return result;    }        -------------------- after (建议)  --------------------        abstract class Operate {        abstract int compute(int numberA, int numberB);    }        class AddOperate extends Operate {        @Override        int compute(int numberA, int numberB) {            // TODO 在这里处理相关逻辑            return numberA + numberB;        }    }        ... SubOperate, MulOperate, DivOperate 也和 AddOperate一样这里就不一一贴出        public static int getResult(int numberA, int numberB, String operate) {        int result = 0;        switch (operate) {            case "+":                result = new AddOperate().compute(numberA, numberB);                break;            case "-":                result = new SubOperate().compute(numberA, numberB);                break;            case "*":                result = new MulOperate().compute(numberA, numberB);                break;            case "/":                result = new DivOperate().compute(numberA, numberB);                break;        }        return result;    }

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

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

  • 虽然在类上有所增加,但是通过多态,把对应操作的逻辑分离出来,使得代码耦合度降低。
  • 如果要修改对应加法的逻辑, 我们只需要修改对应 AddOperate类就可以了。避免直接修改getResult 方法
  • 代码可读性更好,语义更加明确。

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

反射

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

public static  int getResult(int numberA, int numberB, Class clz) {        int result = 0;        try {            return clz.newInstance().compute(numberA, numberB);        } catch (InstantiationException | IllegalAccessException e) {            e.printStackTrace();            return result;        }}public static void main(String[] args) {    // 调用的时候直接传递 class 即可    System.out.println(getResult(1, 2, SumOpearte.class));}根据传入 class 参数,然后生成对应 Opearte处理类,对比多态方式,我们这里采用反射,使得代码耦合度大大降低,如果在增加平方根,平方等计算方式。我们只需要 新增一个 class 继承 Opearte 即可,getResult 不用做任何修改。需要注意的是,不是所有switch语句都需要这样替换, 在面对简单的 switch语句,就不必要了,避免过度设计的嫌疑。如下代码:作者:hyzhan43链接:https://juejin.im/post/5dafbc02e51d4524a0060bdd来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

public String getResult(int typeCode) {        String type = "";        switch (typeCode) {            case 0:                type = "加法";                break;            case 1:                type = "减法";                break;            case 2:                type = "乘法";                break;            case 3:                type = "触发";                break;        }        return type;}

最后

以上就是我在编码上的一些小建议,如有不妥,欢迎大家一起交流学习。


作者:hyzhan43
链接:https://juejin.im/post/5dafbc02e51d4524a0060bdd

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值