小心使用对象引用

        在类代码的设计中, 大多数程序员喜欢把数据成员声明为私有的,并提供共有的访问和设置的方法。这也是公认的比较好的方式。类似:
public class TestClone
{
    private String name;
    private Date date;

    public Date getDate()
    {
        return date;
    }

    public void setDate(Date date)
    {
        this.date = date;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

}
这里有个很微妙的问题,就是
public Date getDate()
    {
        return date;
    }
这个函数,它返回的是一个指向可变对象的引用,使用不慎的话容易引发不易觉察的错误。举例如下:
public class Test
{

    public static void main(String[] args) throws InterruptedException
    {
        // TODO Auto-generated method stub
        TestClone t = new TestClone();
        t.setDate(new Date());
        Date date = t.getDate();
        System.out.println(date);
        date.setDate(20);
        System.out.println(t.getDate());
    }

}
程序输出:
Wed Feb 07 21:31:09 CST 2007
Tue Feb 20 21:31:09 CST 2007
分析:通过 Date date = t.getDate();,使得date和t.date指向了同一个对象。对date应用更改方法会自动改变t.date的值的。这一点需要小心使用,如果需要返回一个指向可变对象的引用,我们需要先克隆它。一个克隆是一个对象放在新位置的精确拷贝。
修改以后的代码如下:
public Date getDate()
    {
        return (Date) date.clone();
    }
注:只要需要返回指向可变对象的引用就应该使用clone。
### 回答1: 虚引用(PhantomReference)是Java中四种引用类型之一,用于在对象被垃圾收集器回收时收到通知。虚引用并不会影响对象的生命周期,而是在对象被回收时,虚引用对象将被加入一个与之关联的引用队列(ReferenceQueue)中,以便在对象被回收时进行处理。 下面是一个虚引用使用示例,假设有一个需要手动清理的资源池,当对象从池中被移除时,可以将其包装成一个虚引用,然后在资源池的清理线程中监视虚引用队列,当虚引用对象出现在队列中时,说明该对象已经被垃圾收集器回收,可以将其相应的资源释放。 ```java public class ResourcePool { private Map<Object, PhantomReference<Object>> pool; private ReferenceQueue<Object> queue; public ResourcePool() { pool = new HashMap<>(); queue = new ReferenceQueue<>(); } public synchronized void addResource(Object resource) { PhantomReference<Object> ref = new PhantomReference<>(resource, queue); pool.put(resource, ref); } public synchronized void removeResource(Object resource) { pool.remove(resource); } public void cleanUp() { Reference<?> ref; while ((ref = queue.poll()) != null) { Object resource = ref.get(); if (resource != null) { // Do clean-up } } } } ``` 在上面的代码中,我们创建了一个ResourcePool类来管理资源,addResource方法用于将资源添加到池中,并将其包装成一个虚引用对象;removeResource方法用于从池中移除资源;cleanUp方法用于清理资源池中的虚引用对象,如果虚引用对象被加入到了队列中,说明对应的资源已经被垃圾收集器回收,可以在此时执行资源的清理操作。 需要注意的是,虚引用的get方法始终返回null,因此不能使用引用对象获取到被引用对象,而是需要通过其他手段来获取被引用对象引用,例如在创建虚引用对象时同时将被引用对象引用保存下来。 ### 回答2: 虚引用(Phantom Reference)是Java中用于管理对象生命周期的一种特殊引用类型。它通常用在需要在对象被GC回收前进行一些清理操作的场景中,比如对象销毁时释放一些关联资源。 使用引用的案例之一是Java中的垃圾回收机制的管理。当一个对象被垃圾回收器标记为可以清理时,虚引用会被放入一个队列中,称为引用队列。通过检查引用队列,程序可以得知对象即将被销毁,从而执行一些相应的清理操作。 举个例子,假设我们有一个较大的对象,它占用了大量的内存资源。在这种情况下,我们可以使用引用来及时释放这些资源。首先,我们创建一个虚引用并关联到该对象上。然后,在对象即将被回收之前,垃圾回收器将把虚引用放入引用队列中。通过检查引用队列,我们可以得知对象即将被销毁,于是可以在销毁之前释放所占用的资源,比如关闭文件、释放网络连接等。 虚引用使用案例也可以在一些缓存场景中找到。当一个对象被从缓存中移除时,我们可以使用引用来执行一些清理操作,比如将对象持久化到磁盘,以便下次需要时可以快速恢复。 总结来说,虚引用使用案例是对垃圾回收过程的管理和对象销毁前的资源释放。通过虚引用,我们可以在对象被GC回收前进行一些必要的清理操作,从而提高程序的性能和资源利用效率。 ### 回答3: 虚引用(Phantom Reference)是Java中一种最弱的引用类型。它的主要作用是跟踪对象被垃圾回收的状态。虚引用并不能直接通过get()方法获取到引用对象,而是通过创建一个引用队列和虚引用一起使用使用引用的一个典型案例是在对象被回收时执行一些清理操作。当虚引用对象被垃圾回收器回收时,会将其放入引用队列中,这时可以通过判断引用队列中是否有虚引用对象从而执行相应的清理操作。比如可以在虚引用对象被回收时,关闭打开的文件、释放占用的资源等。 下面是一个使用引用的简单示例: ```java import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; public class PhantomReferenceExample { public static void main(String[] args) { Object obj = new Object(); ReferenceQueue<Object> queue = new ReferenceQueue<>(); PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue); // 在这里执行一些操作,比如打开文件 obj = null; // 解除强引用,使对象成为垃圾对象 // 检查引用队列,判断对象是否被回收 Reference<?> ref; while ((ref = queue.poll()) != null) { if (ref == phantomRef) { // 执行清理操作,比如关闭文件 // ... } } } } ``` 在上述示例中,创建了一个虚引用phantomRef引用了一个Object对象obj,并将其放入引用队列queue中。通过设置obj为null,解除对obj的强引用,使其成为垃圾对象。当垃圾收集器回收obj时,会自动将phantomRef放入引用队列中。通过检查引用队列,可以判断obj是否被回收,并在此时执行清理操作。 需要注意的是,虚引用并不会延长对象的生命周期,只是提供了一个通知的机制。因此,在使用引用时需要小心,避免出现对象在程序中仍然被引用的情况下被回收。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值