5.6 数据类型和应用

基本类型与引用类型、强引用和弱引用java

Java中数据类型可分为两大类:引用类型(reference)和基本类型(primitive)。

1)基本类型有8种:boolean、char、byte、short、int、long、float、double。函数

  它们都有相应的包装类,这些包装类都属于引用类型,它们依次是:Boolean、Character、Byte、Short、Integer、Long、Float、Double。布局

2)引用类型:全部Java对象都是经过对象引用(Object References)进行访问的,相似于C++中的指针,这个引用指向堆heap中的某块区域,实际的对象存在于heap中。例如,声明以下代码:编码

int prim = 10;
Integer refer = new Integer(10);

这二者在内存中的布局以下图所示:spa

 

Java/Android中有四种引用类型,分别是:

1. Strong reference - 强引用

  实际编码中最多见的一种引用类型。常见形式如:A a = new A();等。强引用自己存储在栈内存中,其存储指向对内存中对象的地址。通常状况下,当对内存中的对象再也不有任何强引用指向它时,垃圾回收机器开始考虑可能要对此内存进行的垃圾回收。如当进行编码:a = null,此时,刚刚在堆中分配地址并新建的a对象没有其余的任何引用,当系统进行垃圾回收时,堆内存将被垃圾回收。线程

SoftReference、WeakReference、PhantomReference都是类java.lang.ref.Reference的子类。Reference做为抽象基类,定义了其子类对象的基本操做。Reference子类都具备以下特色:指针

  1) Reference子类不能无参化直接建立,必须至少以强引用对象为构造参数,建立各自的子类对象;code

2) 由于1中以强引用对象为构造参数建立对象,所以,使得本来强引用所指向的堆内存中的对象将再也不只与强引用自己直接关联,与Reference的子类对象的引用也有必定联系。且此种联系将可能影响到对象的垃圾回收。根据不一样的子类对象对其指示对象(强引用所指向的堆内存中的对象)的垃圾回收不一样的影响特色,分别造成了三个子类,即SoftReference、WeakReference和PhantomReference。对象

 2. Soft Reference - 软引用

A a = new A();
SoftReference<A> srA = new SoftReference<A>(a);

 

   经过对象的强引用为参数,建立了一个SoftReference对象,并使栈内存中的wrA指向此对象。blog

此时,进行以下编码:a = null,对于本来a所指向的A对象的垃圾回收有什么影响呢?

  当 a = null后,堆内存中的A对象将再也不有任何的强引用指向它,但此时尚存在srA引用的对象指向A对象。当第一次调用srA.get()方法返回此指示对象时,因为垃圾回收器颇有可能还没有进行垃圾回收,此时get()是有结果的,这个很好理解。当程序执行System.gc();强制垃圾回收后,经过srA.get(),发现依然能够获得所指示的A对象,说明A对象并未被垃圾回收。

那么,软引用所指示的对象何时才开始被垃圾回收呢?须要知足以下两个条件:

  1.当其指示的对象没有任何强引用对象指向它;    

  2.当虚拟机内存不足时。

所以,软引用变相的延长了其指示对象占据堆内存的时间,直到虚拟机内存不足时垃圾回收器才回收此堆内存空间。

 3. Weak Reference - 弱引用

一样的,弱引用的通常使用形式以下:

A a = new A();
WeakReference<A> wrA = new WeakReference<A>(a);

 

当没有任何强引用指向此对象时,其垃圾回收又具备什么特性呢?

  当 a = null 后,堆内存中的A对象将再也不有任何的强引用指向它,但此时尚存在wrA引用的对象指向A对象。当第一次调用srA.get()方法返回此指示对象时,因为垃圾回收器颇有可能还没有进行垃圾回收,此时get()是有结果的;当进行垃圾回收后,wrA.get()将返回null,代表其指示对象进入到了垃圾回收过程当中。所以,对弱引用特色总结为:

  WeakReference不改变原有强引用对象的垃圾回收时机,一旦其指示对象没有任何强引用对象时,此对象即进入正常的垃圾回收流程

  那么,依据此特色,极可能有疑问:WeakReference存在又有什么意义呢?

  其主要使用场景见于:当前已有强引用指向强引用对象,此时因为业务须要,须要增长对此对象的引用,同时又不但愿改变此引用的垃圾回收时机,此时WeakReference正好符合需求,常见于一些与生命周期的场景中。

例如:结合静态内部类和WeakReference来解决Activity中可能存在的Handler内存泄露问题。

  定义Handler时常会收到一个警告信息:This Handler class should be static or leaks might occur ...

  大体的意思是建议将Handler定义成内部静态类,并在此静态内部类中定义一个WeakReference的引用,因为指示外部的Activity对象。

  问题分析:Activity具备自身的生命周期,Activity中新开启的线程运行过程当中,可能此时用户按下了Back键,或系统内存不足等但愿回收此Activity,因为Activity中新起的线程并不会遵循Activity自己的什么周期,也就是说,当Activity执行了onDestroy,因为线程以及Handler 的HandleMessage的存在,使得系统本但愿进行此Activity内存回收不能实现,由于非静态内部类中隐性的持有对外部类的引用,致使可能存在的内存泄露问题。

  所以,在Activity中使用Handler时,一方面须要将其定义为静态内部类形式,这样可使其与外部类(Activity)解耦,再也不持有外部类的引用,同时因为Handler中的handlerMessage通常都会多少须要访问或修改Activity的属性,此时,须要在Handler内部定义指向此Activity的WeakReference,使其不会影响到Activity的内存回收同时,能够在正常状况下访问到Activity的属性。

4.PhantomReference

  对于SoftReference和WeakReference,还有一个构造器参数为ReferenceQueue<T>,当SoftReference或WeakReference所指示的对象确实被垃圾回收后,其引用将被放置于ReferenceQueue中。注意上文中,当SoftReference或WeakReference的get()方法返回null时,仅是代表其指示的对象已经进入垃圾回收流程,此时对象不必定已经被垃圾回收。而只有确认被垃圾回收后,若是ReferenceQueue,其引用才会被放置于ReferenceQueue中。

与SoftReference或WeakReference相比,PhantomReference主要差异体如今以下几点:

  • PhantomReference只有一个构造函数PhantomReference(T referent, ReferenceQueue<? super T> q),所以,PhantomReference使用必须结合ReferenceQueue
  • 无论有无强引用指向PhantomReference的指示对象,PhantomReference的get()方法返回结果都是null。

  虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,若是发现它还有虚引用,就会在回收对象的内存以前,把这个虚引用加入到与之关联的引用队列中。

相关文章
相关标签/搜索