Java 开发中如何正确的踩坑

点击上方 "程序员小乐"关注公众号, 星标或置顶一起成长

每天早上8点20分, 第一时间与你相约

每日英文

Some people treat you well because you treat them well; while some treat you well because they need something from you.

有的人对你好,是因为你对他好;有的人对你好,是因为懂得你的好。

每日掏心话

这世上,没有什么歧途不可以回头,没有什么错误不可以改正。一个真心向善的念头,是最罕有的奇迹,好像佛桌上开出的花朵。


来自:mafly | 责编:乐乐

链接:cnblogs.com/mafly/p/trap.html

640?wx_fmt=jpeg

程序员小乐(ID:study_tech)第 647 次推文   图片来自网络

   正文   


为什么说一个好的员工能顶 100 个普通员工?

我们的做法是,要用最好的人。我一直都认为研发本身是很有创造性的,如果人不放松,或不够聪明,都很难做得好。你要找到最好的人,一个好的工程师不是顶10个,是顶100个。

所以,在核心工程师上面,大家一定要不惜血本去找,千万不要想偷懒只用培养大学生的方法去做。最好的人本身有很强的驱动力,你只要把他放到他喜欢的事情上,让他自己有玩的心态,他才能真正做出一些事情,打动他自己,才能打动别人。所以你今天看到我们很多的工程师,他自己在边玩边创新。

所以,找最好的人,要给他做他喜欢和擅长的事情。研发人员千万不要去管太严,一管就“死”了。工程师很讨厌跟规章制度打交道,作汇报他都很烦,大家不要管他,让用户去管他。他做好了一个产品,用户表扬他,这个大神多牛逼。他做不好了,用户骂他,他自己赶紧去改。

再谈阿里巴巴 Java 开发手册

之前在这个手册刚发布的时候看过一遍,当时感觉真是每个开发者都应该必读的一本手册,期间还写过一篇关于日志规约的文章:

http://www.cnblogs.com/mafly/p/slf4j.html

最近由于在总结一些我们日常开发中容易忽略的问题,可能是最低级的编码常见问题,往往这也是最最容易忽略的,所以,又重新看了一遍这个手册,好像最近它也更新到了 1.2 版本。

这个手册目的就是让我们尽可能少踩坑,杜绝踩重复的坑。我接下来就打算试着写一些“坑”出来,来看看我们如何一不留神踩坑的,以及如何用正确的姿势跳出坑。

随随便便写出 NPE

首先声明一个 User 对象,接下来所有代码可能都会用到这个对象做演示,在下面将不在赘述。很简单,不上代码,上图片:

640?wx_fmt=png

1.自动解箱抛 NPE

代码只有一行,再简单不过了:int method() { return new User().getId(); }

640?wx_fmt=png

踩坑姿势:包装类型为 null 时,进行自动转换为基本数据类型报错。

2.级联调用易产生 NPE

这段代码有点容易迷惑人,因为它进行了集合元素的 isEmpty 判断,按说不会出问题了吧。看代码:

static void method1() {
    List<User> list = new ArrayList<User>();
    list.add(new User());

    if (!CollectionUtils.isEmpty(list)) {
        for (User user : list) {
            System.out.println("userid:" + user.getId().toString());
        }
    }
}

不废话,看运行结果:

640?wx_fmt=png

没错,还是报错了。

踩坑姿势:其实就是尽管你在之前做了对象不为空的判断,但你并不能保证对象中的值不为空,而且这时候去级联调用就会抛 NPE 。

手册中关于 NPE 的描述:

防止 NPE 是调用者的责任。即使被调用方法返回空集合或者空对象,对调用者来说,也并非高枕无忧,必须考虑到远程调用失败、序列化失败、运行时异常等场景返回 null 的情况。

级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE

3.关于 Equals

这是日常开发中用于相等比较使用最多的方法了吧,因为当年谁没被 == 坑过阿。现在一般我们都会这么写:user.getName().equals("mafly");

640?wx_fmt=png

踩坑姿势:一不小心使用了 null 值调用了 Equals 方法。

equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

4.Map 下的 NPE

Map 应该是我们开发中使用最频繁的了,最常用的可能有 

640?wx_fmt=png

踩坑姿势:可能我们知道 ConcurrentHashMap 的 K/V 都不能为空,但我们有时候并不知道传进来的值是否为空。

由于 HashMap 的干扰,很多人认为 

Map 类集合 K/V 能不能存储 null 值的情况,如下表格:

640?wx_fmt=png


简单聊聊常用的集合

5.foreach 遍历集合删除元素

大家应该都知道,在遍历集合时对元素进行 add/remove 操作要使用 Iterator,使用 for 循环时会报错,一定会报错吗?看代码:

public static void main(String[] args) {
    List<String> a = new ArrayList<>();
    a.add("1");
    a.add("2");
    a.add("3");

    for (String temp : a) {
        if ("2".equals(temp)) {
            a.remove(temp);
        }
    }

    Iterator<String> it = a.iterator();
    while (it.hasNext()) {
        String temp = it.next();
        if ("2".equals(temp)) {
            it.remove();
        }
    }
}

应该会报错的吧?因为在 for 循环中移出了元素,如果你运行了就会惊讶的,输出如下:

640?wx_fmt=png

不解释其中原因了,感兴趣的可以看这篇文章:

http://blog.csdn.net/bimuyulaila/article/details/52088124

不管是不是倒数第二个元素才没问题,我们依然要注意不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式(代码第二种),如果并发操作,需要对 Iterator 对象加锁。

6.Arrays.asList() 数组转换集合

这个工具类应该都用过,可以很方便的把数组转换为集合,直接看结果吧:

640?wx_fmt=png

踩坑姿势:Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。asList() 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。

7. toArray() 集合转换数组

当我们需要把一个集合转换为数组时,往往会调用 toArray() 方法,如果你用的是无参的这个可以吗?

640?wx_fmt=png

当然不可以啦!会报 ClassCastException 异常。

踩坑姿势:直接使用 toArray() 无参方法返回值只能是 Object[]类,若强转其它类型数组将会抛异常。T[] toArray(T[] a); 有参数这个方法

代码如下:

 
                                                  

8. subList 的使用

集合中的 subList 是用于来返回某一部分的视图内容的,可能我们不是很常用,但是其中有好多坑的,直接看代码:

640?wx_fmt=png

640?wx_fmt=png

这次我们从输出来看上面的所有关于 subList 的代码。

  • 18行:当你原始集合大小没有那么大时,毫无疑问抛异常。

  • 20-21行:得到一个新的集合,我们往新集合中增加一条数据。

  • 23-26行:遍历原始集合,竟然 size=2 了,而且往新集合中增加的数据存在与原始集合。

  • 28-31行:移除新集合中一条数据,遍历新集合。

  • 33-37行:原始集合增加一条数据并遍历。

  • 40-42行:遍历新集合,抛出 ConcurrentModificationException 异常。

从上述代码中,我们应该可以得出如下结论:返回的新集合是靠原来的集合支持的,修改都会影响到彼此对方。在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均产生异常。

先总结一下

写到这只是其中关于异常部分的一些坑吧,还有另外一些令人异常惊讶的“我的天吶”的问题,由于篇幅太长了点,感觉不能再写下去了,过两天再接着写吧。

异常真的是一个有意思的问题。

640?wx_fmt=png

欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,学习能力的提升上有新的认识,欢迎转发分享给更多人。

欢迎各位读者加入程序员小乐技术群,在公众号后台回复“加群”或者“学习”即可。

猜你还想看

Redis 面试最常被问到21个知识点总结

我所理解的架构,不看别后悔!

超级全面的权限系统设计方案

640?wx_fmt=png

嘿,你在看吗640?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值