代码这样写,它不香吗

前言

好的代码习惯可以让开发更有效率,阅读更有流畅,后续维护更方便。

本文记录的是我在JAVA开发中使用的一些小技巧,也有一些是和同事交流分享的,更有一部分是在浏览博客中有所得,下面进入正题。

避免过多过于频繁地创建java对象

反例1

public class Example{
	public void clear(){
		// 清空数据
	}
}	



	for ( ) {
		Example	ex = new Example();
	    ex.create().andIdEqual();
	    // 查询数据
	    mapper.select(ex);
	}

反例1中在每次的for循环中都会进行 new Example() ,这样会导致系统要在heap中多次创建对象,占用内存,并且还要花费时间进行GC。
建议尽量重用已创建的对象,可提升程序执行效率。

正例1

	Example	ex = new Example();
	for ( ) {
	    ex.create().andIdEqual();
	     // 查询数据
	    mapper.select(ex);
	    ex.clear();
	}

反例2

	Example	ex = new Example();
	if (i == 1) {
	    ex.create().andIdEqual();
	     // 查询数据
	    mapper.select(ex);
	}

反例2中,无论 i==1 是否成立,程序都要创建一个Example对象,效果不如正例2。

正例2

	if (i == 1) {
		Example	ex = new Example();
	    ex.create().andIdEqual();
	     // 查询数据
	    mapper.select(ex);
	}

减少重复计算

反例

for  (int  i=0; i< list.size(); i++)  {
	// do something
}

反例中每次循环都要进行计算 list.size() ,这没有必要,不如在初始化阶段进行,如正例所示

正例

for  (int i=0, listSize = list.size(); i< listSize; i++)  {
	// do something
}

尽量使用已缓存的对象

反例

        BigDecimal a = new BigDecimal("0");
        BigDecimal b = new BigDecimal("10");

BigDecimal会在加载时将一些常用的数值缓存到常量池中,能使用缓存值尽量使用缓存值,可以节省加载时间及内存空间。
同样,遇到别的类型在创建时先检查一下是否有已缓存的数据。

正例

        BigDecimal a = BigDecimal.ZERO;
        BigDecimal b = BigDecimal.TEN;

StringBuffer,StringBuilder

反例

    public void test2() {
        StringBuffer sbu = new StringBuffer();
        sbu.append("123").append(456);
        System.out.println(sbu.toString());
    }

都知道StringBuffer线程安全但执行效率低,StringBuilder线程不安全但执行效率高。
在方法体中,建议使用StringBuilder提升执行效率,原因是执行方法时都是在stack内操作的,不存在线程不安全的问题。

正例

    public void test2() {
        StringBuilder sbu = new StringBuilder();
        sbu.append("123").append(456);
        System.out.println(sbu.toString());
    }

获取中间数,注意防止溢出

反例

    public void test2() {
        int start = 2147483500;
        int end = 2147483647;
        int mid = (start + end) / 2;
        System.out.println(mid);// 结果是-74
    }

反例中,start + end 很明显会溢出,得到的mid结果肯定是负值,和实际结果不符。

正例

    public void test2() {
        int start = 2147483500;
        int end = 2147483647;
        int mid = start + (end - start) / 2;
        System.out.println(mid);// 结果是2147483573
    }

类型之间的转换

反例

    public void test2() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("a", "abc");
        map.put("b", 123);

		// 获取b的值
        Integer b = (Integer) map.get("b");
        System.out.println(b);
    }

曾经的痛 当时有人将map中b的值改为 字符串123 ,导致在获取b的值进行类型转换时出现类型转换异常,后来改为正例方式,避免了类型转换异常。

正例

    public void test2() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("a", "abc");
        map.put("b", "123");

		// 获取b的值
        Integer b = Integer.valueOf(String.valueOf(map.get("b")));
        System.out.println(b);
    }

String 的 split 方法,传入的分隔字符串是正则表达式

反例

    public void test2() {
        "a.ab.abc".split("."); // 结果为[]
        "a|ab|abc".split("|"); // 结果为["a", "|", "a", "b", "|", "a", "b", "c"]
    }

String 的 split 方法,要求传入的分隔字符串是正则表达式,针对特殊字符(如.\[]()|等)需要做转义处理。

正例

    public void test2() {
        "a.ab.abc".split("\\."); // 结果为["a", "ab", "abc"]
        "a|ab|abc".split("\\|"); // 结果为["a", "ab", "abc"]
    }

Mysql语句中禁止使用双引号

反例

UPDATE sys_user SET user_name = "测试账号" WHERE user_code = "test" and user_no = "no";

mysql语句中禁止使用双引号,双引号会有sql截断风险,建议只使用单引号。
反例中WHERE语句可能会被解析为user_code = “test and user_no = no”,至于为什么会小概率解析成这样,尚未查明原因,为了避免出现问题,我都要求公司的同事sql中只使用单引号。
正例

UPDATE sys_user SET user_name = '测试账号' WHERE user_code = 'test' and user_no = 'no';

数据库字段尽量设置缺省值

反例

CREATE TABLE IF NOT EXISTS sys_user (
user_id INT(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',
user_name VARCHAR(45) DEFAULT '' COMMENT '名称',
user_status INT(2) DEFAULT NULL COMMENT '状态,1正常',
PRIMARY KEY (user_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统用户表';

有一次,我从数据库读user数据进行处理,出现空指针异常,原因是user的status为null,在拆箱时会进行user.getUserStatus().intValue()操作转为基本类型。

if	(user.getUserStatus() == 1)	{	// 报空指针异常
	// do something
}

正例

CREATE TABLE IF NOT EXISTS sys_user (
user_id INT(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',
user_name VARCHAR(45) DEFAULT '' COMMENT '名称',
user_status INT(2) DEFAULT 1 COMMENT '状态,1正常',
PRIMARY KEY (user_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统用户表';

BigDecimal的数值取反

反例

    BigDecimal fuyi = new BigDecimal("-1");
    BigDecimal aa = BigDecimal.TEN.multiply(fuyi);// 结果为-10

正例

	BigDecimal aa = BigDecimal.ZERO.subtract(BigDecimal.TEN);// 结果为-10

正例比起反例,少创建一个对象,并且CPU操作减法比操作乘法更快。

三元运算符

示例
User是对应数据库user表的实体类,user_stat是其中的一个字段。

    User user = service.getOneUser();
    hashMap.put("userStat", user == null ? 9 : user.getUserStat());

经过JVM编译后,JVM会显式调用intValue()方法然后再通过valueOf()将userStat的值转为Integer对象。

    User user = this.service.getOneUser();
    hashMap.put("userStat", Integer.valueOf(user == null ? 9 : user.getUserStat().intValue()));

当数据库中user_stat的值为null时,在调用intValue()会报空指针异常。
使用三元运算符需要注意。

Map

        Map<String, String> map = service.getMap();
        if (map.get("123") == null) {
            map.put("123", "123123");
        }
        System.out.println(map);

可优化为

        Map<String, String> map = service.getMap();
        map.putIfAbsent("123", "123123");
        System.out.println(map);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值