【Java学习笔记】不要把一个非临时可变对象添加入集合中!

 今天再读ArrayList的源码是意外发现了一个令人惊讶的问题:

public E set(int index, E element) 
{
    rangeCheck(index);
    E oldValue = elementData(index);
    elementData[index] = element;//注意这句!
    return oldValue;
}

 注意第三句,它只是简单的把element指向的对象赋给了elementData[index]这意味着如果外界的element更改了,那么ArrayList也会更改!
 为了证明这一点,我做了个实验:

class Demo implements Comparable<Demo>
{
    int i = 0;
    @Override
    public String toString()
    {
        // TODO Auto-generated method stub
        return String.valueOf(i);
    }
    @Override
    public int compareTo(Demo o)
    {
        // TODO Auto-generated method stub
        return i - o.i;
    }
}
Collection<Demo> collection = null;

List<Demo> list = new LinkedList<>();
Set<Demo> set = new HashSet<>();
Queue<Demo> queue = new ArrayDeque<>();
Demo demo = new Demo();

collection = queue;

collection.add(demo);

System.out.println(collection);
demo.i = 5;//更改
System.out.println(collection);

[0]
[5]

 事实证明确实变了。
 所以这就告诉我们,如果我们要使用一个可变对象的集合时,千万不能把之后还要使用的对象加入集合中。换而言之:

A a = new A();//A是一个可变类
list.add(a);//NO!!!
a.modify();

 那么为什么平时我们没有意识到这有什么问题呢?这是因为我们平时用的类大多都是不可变类,例如String。实际上String中的方法根本就不会改变自身:

String s = new String("abc");
List<String> list = new LinkedList<>();

list.add(s);

System.out.println(collection);//[abc]
s.toUpperCase();//不改变s
System.out.println(s);//还是abc
System.out.println(collection);//还是[abc]

 然而如果你用StringBuffer代替String就会发现:

StringBuffer sBuffer = new StringBuffer("abc");
List<StringBuffer> list = new LinkedList<>();
list.add(sBuffer);

System.out.println(collection);//[abc]
sBuffer.append("def");
System.out.println(collection);//[abcdef]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值