Java 程序员最容易犯的 7 个错误

这是我参与11月更文挑战的第30天,活动详情查看:2021最后一次更文挑战

希望你看到这遍文章,直呼好家伙,赶紧带给你的小伙伴们看看。

1 新人到公司启动项目要几天

这点我是深恶痛绝的,一个理想的状态应该是新人拿到电脑,装好环境,打开 IDE,导入项目,项目运行成功,如果你的项目依赖于特定的 IDE, 特定的插件版本,特殊的环境变量,这个时候你要么是文档写的明明白白,要么你就需要重新构建一下你的系统了。

2 将 Array 转换成 ArrayList 时出错

一些开发者经常用这样的代码将 Array 转化为 ArrayList

List<String> list = Arrays.asList(arr)
复制代码

Arrays.asList() 的返回值是一个 ArrayList 类的对象,这个 ArrayList 类是 Arrays 类里的一个私有静态类,并不是我们常说的那个集合 java.util.ArrayList。

java.util.Arrays.ArrayList 有 set() / get() / contains() 方法,但是并不提供任何添加元素的方法,因此它的长度是固定的。如果你希望得到一个 java.util.ArrayList 类的实例,你应该这么做:

ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));
复制代码

ArrayList 的构造函数可以接受一个 Collection 实例,而 Collection 是 java.util.Arrays.ArrayList 的父类。

3 检查 array 里是否包含某个值时出错

一些开发者会这么写:

Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
复制代码

上面的代码可以工作,但是其实没必要把 list 转为 set,这有些浪费时间,简单的写法是这样的:

Arrays.asList(arr).contains(targetValue);
复制代码

或者这样的

for(String s: arr){
    if(s.equals(targetValue))
        return true;
}
return false;
复制代码

这两种写法中,前者可读性更好。

4 遍历 list 移除元素时报错

这个我们之前在 ArrayList 和 LinkedList 中的时候说过原理,这里直接上 case 。

下面的代码在迭代时移除了元素:

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
for (int i = 0; i < list.size(); i++) {
    list.remove(i);
}
System.out.println(list);
复制代码

得到的结果是 [b,d]。

这种代码的问题在于,当元素被移除时,list 的长度也随之变小了,index 也同时发生了变化。所以,如果你想要在循环中使用 index 移除多个元素,它可能不能正常工作。

你可能认为在循环中删除元素的正确方法是迭代器,比如 foreach 循环看起来就是一个迭代器,其实这样还是有问题。

考虑以下代码(代码 1):

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
 
for (String s : list) {
    if (s.equals("a"))
        list.remove(s);
}
复制代码

会抛出 ConcurrentModificationException 异常,为什么,就是因为迭代器中有一个 Check 方法。

要正确地在遍历时删除元素,应该这么写(代码 2):

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
    String s = iter.next();
 
    if (s.equals("a")) {
        iter.remove();
    }
}
复制代码

你必须在每次循环里先调用 .next() 再调用 .remove()。

5 访问级别设置的过高

这点确实是,可能是为了方便,也可能是写顺手了,我们总是喜欢使用 public ,顺手写来,很少考虑这个方法/属性是否真的需要这样设置,实际上,我们应该尽可能低的设置访问级别。

6 在 switch 块中使用多个 String

这里就有点意思了,在 switch 中使用 String 不是说不行,只是太不友好,很容易出错,搞不好还会漏掉某些分支,更推荐使用的 Enum 这样保证所有人不会在 switch 中出错,而且还可以一眼看出来所有的可能分支。

7 总是使用项目定制的 StringUtils

说出这个你可能会非常惊讶,为什么会这样呢?难道我还不能自己创建一个工具类了。但是问题就是现在已经有很多成熟的 jar 可以供我们使用了,比如 Apache Commons,Google Guava,Joda Data, Hutool,这些工具难道不香嘛?你就不能稍微看一看这些优秀的开源框架嘛?

猜你喜欢

转载自juejin.im/post/7036386763250204685