Java 中 List.subList() 方法的使用陷阱

转载请注明本文出自 clevergump 的博客:http://blog.csdn.net/clevergump/article/details/51105235, 谢谢!


前言

本文原先发表在我的 iteye博客: http://clevergump.iteye.com/admin/blogs/2211979, 但由于在 iteye发表的这篇文章的某些渲染曾经出现过一些问题, 我曾发过多封邮件向 iteye 的工作人员进行反馈, 官方只是在我第一封邮件中回复说会联系技术人员处理, 但是此后就再也没有收到他们的任何回复了, 我后来多次邮件询问进度, 也没有收到新的回复, 及时响应用户的提问和需求, 是提高用户体验和满意度的重要因素. 我想, 即使你们不能搞定或者不想去处理, 也应该给个回复, 即使回复 “我们暂时无法处理”, 也比不回复邮件要好啊. 于是我就决定今后永远放弃 iteye, 但自认为原博客中的这篇文章还是有一定价值的, 于是就在此重新发表一次, 并且今后就维护这篇文章吧.

另外多说一句, 不论你是从事什么行业的什么工作, 只要是和响应客户需求相关的岗位, 都应该主动及时地让客户知道他们所关心的事情的处理进度, 这样才能提高用户体验和满意度. 包括我们做手机 APP 或者 PC 客户端开发的岗位也是如此, 我们的客户端在遇到网络异常, 或者内存不足, 或者一段时间内无响应等特殊情况, 都应该及时主动地给用户弹出一个提示框或对话框. 我们在下载软件时, 显示下载进度条, 在加载图片时, 显示加载进度条. 在用户点击任何一个可能会让他们认为 (包括误认为) 可以点击的地方, 都必须要么进行页面变化, 要么弹出一个对话框或提示框, 不能什么都不处理, 尤其是对于那些设计时没有添加点击功能, 但却有可能被用户误认为可以点击的地方, 也要做相应的用户点击的响应处理……以上这些做法, 都是为了让用户及时知道他们关心的事情的进度, 都是提升用户体验的做法. 好了, 前言就扯这么多吧.


正文

做 Java 或 Android 开发的朋友, 一定都很熟悉 String 类中的 subString() 方法. 下面我们先来看一个关于该方法的小例子. 假如我们有如下需求: 随意设定一个字符串, 然后从中取出一个子字符串, 然后在该子字符串的末尾添加一些新的字符, 但要保证原先的字符串不变. 这个需求对你来说实在是 so easy, 于是你迅速写出了如下代码:

public class SubStringDemo {
   

    private static String str;
    private static String subStr;

    public static void main(String[] args) {
        subStringTest();
    }

    private static void subStringTest() {
        str = "01234";
        subStr = str.substring(2, str.length());

        print();
        subStr += "5";
        System.out.println("---------此时将 subStr 中增加一个字符 '5' ----------");
        print();
    }

    private static void print() {
        System.out.println("str    = " + str);
        System.out.println("subStr = " + subStr);
    }
}

你假设原字符串为 “01234”, 通过 subString() 方法从该字符串中取出一个子字符串 “234”, 然后在这个取出的子字符串的末尾添加一个新的字符’5’, 这样子字符串就变为 “2345”, 而原字符串则不变, 仍为 “01234”.

我们看下运行结果:

这里写图片描述

从运行结果来看, 代码确实没问题. IQ极高的你甚至有些愤愤不平, “这么 low 的需求, 简直就是在欺 (wu) 负 (ru) 哥的智商嘛”, 不知情的人, 还以为你在卫生间看到了下面这张图呢:

这里写图片描述

哈哈, 你可能确实有点屈才了. ^_^

没关系, 既然你智商很高, 我们就改个需求吧, 要求你能快速响应我们的需求变化, 要体现在代码中. 你说, 没问题, 尽管放马过来吧, 哥都能 hold 住. 于是需求改为如下内容: 将原需求中的字符串改为 List (也就是 java.util.List ), 将原需求中所有对字符串的要求都移植到对 List 的要求中. 具体来说就是, 随意设定一个 List 的实现类对象, 然后从中取出一个子 List , 然后向该子 List 中添加一些新的元素, 但要保证原先的 List 不变.

看到这个需求后, 估计你的心情可能又会像上面那张图那样吧. 这个变化, so easy. StringsubString() 方法, 难道 List 就没有 subList() 方法??? 人要学会融会贯通嘛, 所以答案是显而易见的. 如果这都不是欺 (wu) 负 (ru) 哥的智商的话, 那么世界上就不存在 “欺 (wu) 负 (ru) 智商” 的说法了. 但是, 你终究还是平复了你的心情, 然后奋笔疾书, 快速写下了如下代码:

private static List list;
private static List subList;

private static void subListTest(Class<? extends List> listClazz) 
        throws IllegalAccessException, InstantiationException {
    if (listClazz == null) {
        throw new IllegalArgumentException(listClazz + " is null.");
    }

    list = listClazz.newInstance();
    list.clear();
    for (int i = 0; i < 5; i++) {
        list.add(i);
    }

    subList = list.subList(2, list.size());
    subList.add(5);
}

和先前 String 需求中设定的数字类似, 你在原 List 中设定该 List 中存有5个元素, 分别是整数 0, 1, 2, 3, 4. 然后将第2个元素到最末一个元素全部取出, 作为子 List. 然后向取出的这个子 List 中添加一个整数5. 写完这个代码后, 你甚至根本没有进行自测, 就非常自信地把代码直接交给了测试MM.

然而, 过了一会儿, 测试MM反馈说, 你的代码有bug. 在子 List 新增元素后, 原 List 也变了. 你很诧异, 不可能呀, 不应该呀, 子 List 的变化, 怎么会影响到原 List 呢? 不可能的, 一定是测试MM搞错了, 你心里或许在想, 难道是因为哥长得帅, 妹子想借此搭讪哥? ^_^ 但是, 测试MM一脸正经地告诉你, 确实有bug, 你的确需要修复, 先提个 bug 跟进的单子吧. 此刻, 你感觉到情况似乎有些不妙, 为了谨慎起见, 你立刻对原先的代码进行自测, 在原先代码的基础上增加了一些日志输出语句, 于是就有了如下代码:

public class SubListDemo {
   
    private static List list;
    private static List subList;

    public static void main
  • 29
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值