如何写出高效的代码?

1. 优化你的程序,拒绝创建不必要的对象

如果你的变量,后面的逻辑判断,一定会被赋值;或者说,只是一个字符串变量,直接初始化字符串常量就可以了,没有必要愣是要new String().

反例:

String s = new String ("欢迎关注公众号");

正例:

String s = “欢迎关注公众号”

2. 初始化集合时,指定容量

阿里的开发手册,也明确提到这个点:

Image

假设你的map要存储的元素个数是15个左右,最优写法如下

 //initialCapacity = 15/0.75+1=21
 Map map = new HashMap(21);
 
 又因为hashMap的容量跟2的幂有关,所以可以取32的容量
 Map map = new HashMap(32);

3. 注意检验空指针,不要轻易相信业务,说正常逻辑某个参数不可能为空。

NullPointerException 在我们日常开发中非常常见,我们代码开发过程中,一定要对空指针保持灵敏的嗅觉。

主要有这几类空指针问题:

  • 包装类型的空指针问题

  • 级联调用的空指针问题

  • Equals方法左边的空指针问题

  • ConcurrentHashMap 类似容器不支持 k-v为 null。

  • 集合,数组直接获取元素

  • 对象直接获取属性

「反例:」

public class NullPointTest {
    public static void main(String[] args) {
        String s = null;
        if (s.equals("666")) { //s可能为空,会导致空指针问题
            System.out.println("干货满满");
        }
    }
}

4. 如果变量的初值一定会被覆盖,就没有必要给变量赋初值。

「反例:」

List<UserInfo> userList = new ArrayList<>();
if (isAll) {
    userList = userInfoDAO.queryAll();
} else {
    userList = userInfoDAO.queryActive();
}

「正例:」

List<UserInfo> userList ;
if (isAll) {
    userList = userInfoDAO.queryAll();
} else {
    userList = userInfoDAO.queryActive();
}

5.  注意Arrays.asList的几个坑

  • 「基本类型不能作为 Arrays.asList方法的参数,否则会被当做一个参数。」

public class ArrayAsListTest {
    public static void main(String[] args) {
        int[] array = {1, 2, 3};
        List list = Arrays.asList(array);
        System.out.println(list.size());
    }
}
//运行结果
1
  • 「Arrays.asList 返回的 List 不支持增删操作。」

public class ArrayAsListTest {
    public static void main(String[] args) {
        String[] array = {"1", "2", "3"};
        List list = Arrays.asList(array);
        list.add("5");
        System.out.println(list.size());
    }
}

// 运行结果
Exception in thread "main" java.lang.UnsupportedOperationException
 at java.util.AbstractList.add(AbstractList.java:148)
 at java.util.AbstractList.add(AbstractList.java:108)
 at object.ArrayAsListTest.main(ArrayAsListTest.java:11)

Arrays.asList 返回的 List 并不是我们期望的 java.util.ArrayList,而是 Arrays 的内部类ArrayList。内部类的ArrayList没有实现add方法,而是父类的add方法的实现,是会抛出异常的呢。

  • 「使用Arrays.asLis的时候,对原始数组的修改会影响到我们获得的那个List」

public class ArrayAsListTest {
    public static void main(String[] args) {
        String[] arr = {"1", "2", "3"};
        List list = Arrays.asList(arr);
        arr[1] = "4";
        System.out.println("原始数组"+Arrays.toString(arr));
        System.out.println("list数组" + list);
    }
}

//运行结果
原始数组[1, 4, 3]
list数组[1, 4, 3]

 正确写法:ArrayList<Integer> integersList = new ArrayList<>(Arrays.asList(1,2,3));

6. 注意 ArrayList.toArray() 强转的坑

public class ArrayListTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>(1);
        list.add("codeAmaz");
        String[] array21 = (String[])list.toArray();//类型转换异常
    }
}

因为返回的是Object类型,Object类型数组强转String数组,会发生ClassCastException。解决方案是,使用toArray()重载方法toArray(T[] a)

String[] array1 = list.toArray(new String[0]);//可以正常运行

或者使用jdk8 stream流

Integer[] integersArray2 = integersList.stream().toArray(Integer[]::new);  

7.多线程异步优先考虑恰当的线程池,而不是new thread,同时考虑线程池是否隔离

为什么优先使用线程池?使用线程池有这几点好处呀

  • 它帮我们管理线程,避免增加创建线程和销毁线程的资源损耗。

  • 提高响应速度。

  • 重复利用。

同时呢,尽量不要所有业务都共用一个线程池,需要考虑线程池隔离。就是不同的关键业务,分配不同的线程池,然后线程池参数也要考虑恰当哈。之前写过几篇线程池的,觉得还不错,有兴趣的朋友可以看一下哈

8.优化程序结构,尽量减少方法的重复调用

「反例:」

    public static void listDetail(List<UserInfo> userInfoList) {
        for (int i = 0; i < userInfoList.size(); i++) {
            //重复调用userList.size()方法了
        }
    }

「正例:」

 public static void listDetail(List<UserInfo> userInfoList) {
        int length = userInfoList.size();
        for (int i = 0; i < length; i++) {
            //减少调用userList.size()方法,只在length变量调了一次。
        }
    }

9使用spring事务功能时,注意这几个事务未生效的坑

日常业务开发中,我们经常跟事务打交道,事务失效主要有以下几个场景:

  • 底层数据库引擎不支持事务

  • 在非public修饰的方法使用

  • rollbackFor属性设置错误

  • 本类方法直接调用

  • 异常被try...catch吃了,导致事务失效。

10.直接迭代需要使用的集合,无须在额外操作

直接迭代需要使用的集合,无需通过其它操作获取数据,比较典型就是Map的迭代遍历:

「反例:」

Map<Long, UserDO> userMap = ...;
for (Long userId : userMap.keySet()) {
    UserDO user = userMap.get(userId);
    ...
}

「正例:」

Map<Long, UserDO> userMap = ...;
for (Map.Entry<Long, UserDO> userEntry : userMap.entrySet()) {
    Long userId = userEntry.getKey();
    UserDO user = userEntry.getValue();
    ...
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值