Java ---- 引用类型

对于长期运行的引用程序来说,如果无用的对象所占用的内存空间不能得到及时的释放的话,那么在一个局部的时间内便形成了事实上的内存泄露,如果要及时地释放内存,在Java 中最稳妥的方法就是—-在使用完对象之后立即执行“object=null”语句。当然,这也是一种理想状态。

在JDK中引入了4种对象引用类型,通过如下四种引用类型强行调用垃圾回收方法System.gc()来解决内存泄露问题。

  1. 强引用:在日常编程应用中所用的大多数引用类型都属于强引用类型,方法是显式执行“object=null”语句。
  2. 软引用:被软引用的对象,如果内存空间足够,垃圾回收器不会回收它的,如果内存空间不足,垃圾回收器将回收这些对象所占用的空间。在Java 中软引用相对应着java.lang.ref.SoftReference类。一个对象如果要被软引用,只需将其作为参数传入SoftReference 类的构造方法中就行了。
  3. 弱引用:与前面的软引用相比,被弱引用的对象拥有更短的内存时间(也就是生命周期)。垃圾回收器一旦发现了被弱引用的对象,不管当前内存空间是否不足,都会回收它的内存空间,若引用对应着java.lang.ref.WeakReference类。同样的道理,一个对象如果想被弱引用,只需要将其作为参数传入 WeakReference类的构造方法中就行了。
  4. 虚引用:虚引用不是真是可用的引用类型,完全可以视为一种“形同虚设”的引用类型。设计虚引用类型的目的在于结合引用关联队列,实现对象引用关系的跟踪。在 Java 中许引用对应着 java.lang.ref.PhantomReference 类。一个对象如果要被虚引用,只需将其作为参数传入 PhantomReference 类的构造方法中即可,同时作为参数传入的还用引用关系队列 java.lang.ref.ReferenceQueue 的对象实例。
public class Main {

    public static void main(String[] args) {

        int length = 10;

        //创建强引用
        Set<MyObject> a = new HashSet<>();
        for(int i = 0; i<length; i++)
        {
            MyObject ref = new MyObject("Hard_" + i);
            System.out.println("创建强引用:" + ref);
            a.add(ref);
        }
        a=null;
        System.gc();


        //创建软引用
        Set<SoftReference<MyObject>> sa = new HashSet<>();
        for(int i = 0; i<length; i++)
        {
            SoftReference<MyObject> ref = new SoftReference<MyObject>(new MyObject("Soft_" + i));
            System.out.println("创建软引用:" + ref.get());
            sa.add(ref);
        }
        sa=null;
        System.gc();

        //创建弱引用
        Set<WeakReference<MyObject>> wa = new HashSet<>();
        for(int i = 0; i<length; i++)
        {
            WeakReference<MyObject> ref = new WeakReference<MyObject>(new MyObject("Weak_" + i));
            System.out.println("创建弱引用:" + ref.get());
            wa.add(ref);
        }
        System.gc();

        //创建需引用
        ReferenceQueue<Object> rq = new ReferenceQueue<>(); 
        Set<PhantomReference<MyObject>> pa = new HashSet<>();
        for(int i=0; i<length; i++)
        {
            PhantomReference<MyObject> ref = new PhantomReference<MyObject>(new MyObject("Phantom_" + i), rq);
            System.out.println("创建虚引用:" + ref.get());
            pa.add(ref);
        }
        System.gc();
    }
}
class MyObject
{
    private String id;

    public MyObject(String id)
    {
        this.id=id;
    }
    public String toString()
    {
        return id;
    }
    public void finalize()
    {
        System.out.println("回收对象:"+ id);
    }
}

输出:

创建强引用:Hard_0
创建强引用:Hard_1
创建强引用:Hard_2
创建强引用:Hard_3
创建强引用:Hard_4
创建强引用:Hard_5
创建强引用:Hard_6
创建强引用:Hard_7
创建强引用:Hard_8
创建强引用:Hard_9
回收对象:Hard_3
创建软引用:Soft_0
回收对象:Hard_1
创建软引用:Soft_1
回收对象:Hard_0
创建软引用:Soft_2
回收对象:Hard_9
创建软引用:Soft_3
回收对象:Hard_8
创建软引用:Soft_4
回收对象:Hard_7
创建软引用:Soft_5
回收对象:Hard_6
创建软引用:Soft_6
回收对象:Hard_5
创建软引用:Soft_7
回收对象:Hard_4
回收对象:Hard_2
创建软引用:Soft_8
创建软引用:Soft_9
回收对象:Soft_4
回收对象:Soft_2
创建弱引用:Weak_0
回收对象:Soft_1
创建弱引用:Weak_1
回收对象:Soft_0
回收对象:Soft_5
回收对象:Soft_3
回收对象:Soft_9
回收对象:Soft_8
回收对象:Soft_7
回收对象:Soft_6
创建弱引用:Weak_2
创建弱引用:Weak_3
创建弱引用:Weak_4
创建弱引用:Weak_5
创建弱引用:Weak_6
创建弱引用:Weak_7
创建弱引用:Weak_8
创建弱引用:Weak_9
回收对象:Weak_7
回收对象:Weak_2
回收对象:Weak_1
回收对象:Weak_0
回收对象:Weak_5
回收对象:Weak_4
回收对象:Weak_3
回收对象:Weak_9
回收对象:Weak_8
回收对象:Weak_6
创建虚引用:null
创建虚引用:null
创建虚引用:null
创建虚引用:null
创建虚引用:null
创建虚引用:null
创建虚引用:null
创建虚引用:null
创建虚引用:null
创建虚引用:null
回收对象:Phantom_8
回收对象:Phantom_2
回收对象:Phantom_1
回收对象:Phantom_0
回收对象:Phantom_5
回收对象:Phantom_4
回收对象:Phantom_3
回收对象:Phantom_9
回收对象:Phantom_7
回收对象:Phantom_6

其中,MyObject 中的finalize()方法是告诉垃圾回收器应该执行的操作,该方法从Object类继承而来。在从堆中永久删除对象之前,垃圾回收器调用该对象的Finalize方法。

可见,当a=null时。gc便回收其所占用内存。sa也同理。而wa的话,gc发现立刻回收其内存。pa只是对对象引用关系的跟踪而已,并没有真正的实例存在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值