Java中没有指针,到处都是引用(除了基本类型)。所以,当然,你肯定知道java的引用,并用了很久,但是是不是对此了解地比较全面?而这些引用有什么作用,且有什么不同呢?
Java中有个java.lang.ref包,这里面都是描述引用对象的,包括了Reference,SoftReference,WeakReference和PhantomReference。其中,Reference是基类其他三个类的基类。下面就这几种引用对象做个说明。

强引用(Strong References)
我们每天都在用强引用(如果你每天都在用java的话),一段如下的代码:
HashMap mapRef = new HashMap();
就是通过new HashMap();创建了一个对象(这东西在heap上),并把一个强引用存到了
mapRef引用中。而强引用之为“强”的地方就在于其对垃圾回收器所产生的影响。如果一个对象可以经由一条强引用链可达(也就说这个对象是Strongly reachable),那么就说明这个类不适合被垃圾回收。我们也绝对不希望正在使用的对象一下子了无踪迹了。

但是强引用会对我们的应用产生很“强”的影响。比如:经常会碰到一个问题,缓存。通过Set(以set为例吧)模拟的缓存,在应用运行的过程中,会不断有 大量对象添加到set中。这些对象并不会被GC回收,并且随着对象的增多,我们的内存也会不断变大,终于有一天OutOfMemory啦。其实,set可 能使用频率还不大,HashMap的key-value模式让我们爱不释手,引诱着你去不断地put,put,扑通。。OutOfMemory啦。
对于java这门有魅力,有活力,有朝气,有老气,有垃圾自动回收机制的语言而言,我们不应被上述问题所困扰。

弱引用(Weak Reference)
弱引用,就是不是那种用强制的方式要求对象存在于内存的引用。可以借助垃圾回收器来判断某个对象的可达性,并帮你回收弱引用所引用的对象。如何创建一个弱引用呢:
StringBuffer sbuff = new StringBuffer("What is a WeakReference?");
WeakReference<StringBuffer> wref = new WeakReference
<StringBuffer>(sbuff);

sbbuff=null;//这里的操作,看情况定。在这里主要为了说明,原来强引用的一个对象,被转成一个弱引用来指向。然后通过wref.get()来获取sbuff对象。因为弱引用并没强悍到可以阻止垃圾回收器回收wref引用的对象(这里要区分引用对象和被引用的对象,在创建一个WeakReference时,就有一个引用对象诞生了,它指向了一个被引用的对象),所以可能从某一刻开始,wref.get()就开始给我们null了。
对于上面提到的使用HashMap时,对象过多(并且不删除,而被垃圾回收)会造成的OutOfMemory问题,可以通过WeakHashMap来实现,这样垃圾回收器就会帮我们处理那些时间长了不用,还占地方的类了,而不至于出现
OutOfMemory问题引用队列( ReferenceQueue,何方神圣?)
WeakReference开始返回null时,说明它原来指向的对象已经变成了垃圾。另外也说明这个WeakReference对我们已经没多少用处了。我们需要做点什么来处理这些没用的东西?
逢此危难之际,
ReferenceQueue闪亮登场。据官方资料,其定义为:
Reference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected. 
(当检测到相应的可达性发生改变后,
垃圾回收器就会将注册有此队列的引用对象添加到这个引用队列中。
如何注册一个队列?在
WeakReference的构造函数中,有一个WeakReference(T referent, ReferenceQueue<? super T> q)。所以,当一个WeakReference变成一个死引用时,它就会被添加到这个ReferenceQueue中,只要定期的来处理一下这个ReferenceQueue就可以了。

不同的引用

引用实际上是有好几种的,就如我们在java.lang.ref包中看到的那样,再加上强引用,有4种引用类型:强(Strong)、软(Soft)、弱(Weak)、幻象(Phantom),引用依次从强到弱。接下来,就看看其他的引用。

软引用(Soft Reference)

软引用,跟弱引用功能挺像的。但是软引用指向的对象一般会比弱引用的存活时间长一些,直到内存空间不够时,才会被垃圾回收。一个Weakly reachable对象,是仅仅被WeakReference引用的,并且会被垃圾回收器在下一个垃圾回收周期中丢弃;而一个Softly reachable对象,则会活地时间长一些。

软引用给我们带来了很大的实惠,尤其是缓存的实现。比如,我们有一个缓存池,对于内存比较紧张的情况来说,一旦要达到memory上限时,垃圾回收器就将Soft Reference引用的对象释放掉,以避免OutOfMemory惨剧的发生。

幻象引用(Phantom Reference)

幻象引用,是不同于Soft和Weak的引用。幻象引用对指向对象的引用强度如此之脆弱,以至于调用方法get()时,总是返回null。它的主要作用就是跟踪所指向的对象已经dead了,那么其跟WeakReference的区别是什么呢?

它们的区别就在于:是在什么时候,这个引用对象被添加到引用队列中的。WeakReference是在当其所引用的对象变成Weakly Reachable时被添加到引用队列中的,这发生在一个对象被finalization或被垃圾回收之前的。理论上讲,一个对象在被finalize()时,是可以被“复活”的,但此时WeakReference已经没活力了。对幻象引用来说,只有当其所引用的对象被彻底垃圾回收(从内存中消除)时,才会添加到引用队列中。而幻象引用的get方法总是返回null,就是要避免我们来“复活”一个奄奄一息的对象。

那么幻象引用有何实际作用?

第一、我们可以在监控一个对象什么时候被彻底销毁了。那样,就可以做点什么其他事情(看你是不是有这方面的需求啦)。不过实际中,这种情况也不多的。

第二、因为理论上存在的,可以通过一个对象的finalize()方法“复活”一个对象,那么如果在一次垃圾回收处理时,调用了一个对象的finalize()(这个方法在何时调用不确定),却让它复活了。要再苦苦等待finalize()的执行,还不知道要到猴年马月的(天下大赦可以有,但不是天天有。谁知道啥时候天朝更替,人主易位)。突然就出现了OutOfMemory错误了。

而幻象引用绝对不会再让对象复活,只要被它逮着了,事情就简单了:挂定了!

总而言之,言而总之,归根结底:

引用是关系垃圾回收的。

转载自:http://www.cnblogs.com/ericchen/

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set; class VeryBig{
private static final int SIZE = 10000;
private long[] la = new long[SIZE];
private String ident;
public VeryBig(String id) {
ident = id;
}
@Override
public String toString() {
return ident;
}
protected void finalize() {
System.out.println("finalize...." + ident);
}
} public class Test{
private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();
public static void checkQueue() {
Reference<? extends VeryBig> inq = rq.poll();
if (inq != null) {
System.out.println("in Queue : " + inq.get());
}
}
public static void main(String[] args) {
int size = 10;
System.out.println("--------Soft------------");
LinkedList<SoftReference<VeryBig>> sa = new LinkedList<SoftReference<VeryBig>>();
for (int i = 0; i < size; ++i) {
sa.add(new SoftReference<VeryBig>(new VeryBig("soft" + i), rq));
System.out.println("just created soft: " + sa.getLast().get());
checkQueue();
}
SoftReference<VeryBig> s = new SoftReference<VeryBig>(new VeryBig("soft")); System.out.println("--------Weak------------");
LinkedList<WeakReference<VeryBig>> wa = new LinkedList<WeakReference<VeryBig>>();
for (int i = 0; i < size; ++i) {
wa.add(new WeakReference<VeryBig>(new VeryBig("weak" + i), rq));
System.out.println("just create weak : " + wa.getLast().get());
checkQueue();
}
WeakReference<VeryBig> w = new WeakReference<VeryBig>(new VeryBig("Weak")); System.gc(); LinkedList<PhantomReference<VeryBig>> pa = new LinkedList<PhantomReference<VeryBig>>();
for (int i = 0; i < size; ++i) {
pa.add(new PhantomReference<VeryBig>(new VeryBig("phantom " + i), rq));
System.out.println("just create Phantom : " + pa.getLast().get());
checkQueue();
}
}
} 输出:
--------Soft------------
just created soft: soft0
just created soft: soft1
just created soft: soft2
just created soft: soft3
just created soft: soft4
just created soft: soft5
just created soft: soft6
just created soft: soft7
just created soft: soft8
just created soft: soft9
--------Weak------------
just create weak : weak0
just create weak : weak1
just create weak : weak2
just create weak : weak3
just create weak : weak4
just create weak : weak5
just create weak : weak6
just create weak : weak7
just create weak : weak8
just create weak : weak9
just create Phantom : null
just create Phantom : null
finalize....weak2
finalize....Weak
in Queue : null
finalize....weak9
just create Phantom : null
finalize....weak8
in Queue : null
finalize....weak7
just create Phantom : null
finalize....weak6
finalize....weak5
finalize....weak4
finalize....weak3
finalize....weak1
finalize....weak0
in Queue : null
just create Phantom : null
in Queue : null
just create Phantom : null
in Queue : null
just create Phantom : null
in Queue : null
just create Phantom : null
in Queue : null
just create Phantom : null
in Queue : null
just create Phantom : null
in Queue : null

  

 

Java中引用的详解的更多相关文章

  1. Java中日志组件详解

    avalon-logkit Java中日志组件详解 lanhy 发布于 2020-9-1 11:35 224浏览 0收藏 作为开发人员,我相信您对日志记录工具并不陌生. Java还具有功能强大且功能强 ...

  2. java中的注解详解和自定义注解

    一.java中的注解详解 1.什么是注解 用一个词就可以描述注解,那就是元数据,即一种描述数据的数据.所以,可以说注解就是源代码的元数据.比如,下面这段代码: @Override public Str ...

  3. Java中dimension类详解

    Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788

  4. [转载]java中import作用详解

    [转载]java中import作用详解 来源: https://blog.csdn.net/qq_25665807/article/details/74747868 这篇博客讲的真的很清楚,这个作者很 ...

  5. JAVA中Object类方法详解

    一.引言 Object是java所有类的基类,是整个类继承结构的顶端,也是最抽象的一个类.大家天天都在使用toString().equals().hashCode().waite().notify() ...

  6. Java中反射机制详解

    序言 在学习java基础时,由于学的不扎实,讲的实用性不强,就觉得没用,很多重要的知识就那样一笔带过了,像这个马上要讲的反射机制一样,当时学的时候就忽略了,到后来学习的知识中,很多东西动不动就用反射, ...

  7. java中Class对象详解和类名.class, class.forName(), getClass()区别

    一直在想.class和.getClass()的区别,思索良久,有点思绪,然后有网上搜了搜,找到了如下的一篇文章,与大家分享. 原来为就是涉及到Java的反射----- Java反射学习 所谓反射,可以 ...

  8. java中的static详解

    如果一个类成员被声明为static,它就能够在类的任何对象创建之前被访问,而不必引用任何对象.static 成员的最常见的例子是main( ) .因为在程序开始执行时必须调用main() ,所以它被声 ...

  9. java中static作用详解

    static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何 ...

随机推荐

  1. windows安装并破解navicat.

    1:下载以下两个文件. patchNavicat.exe:  https://pan.baidu.com/s/1ZtV20GUGfZHcXHRTEb5tYg navicatforMysql.exe:  ...

  2. PHP学习必读的20本书

    PHP相关<PHP程序设计>(第2版) –PHP语法和入门最好的书<PHP5权威编程> –PHP入门后升级书<深入PHP:面向对象.模式与实践>(第3版) –理解P ...

  3. iOS 设计模式-委托模式

    委托是指给一个对象提供机会对另一对象中的变化做出反应或者相应另一个对象的行为.其基本思想是协同解决问题. Delegate的使用场合 对象A内部发生了一些事情,想通知对象B 对象B想监听对象A内部发生 ...

  4. 浏览器css hack

    (1)*:  IE6+IE7都能识别*,而标准浏览器FF+IE8是不能识别*的; (2)!important: 除IE6不能识别 !important外,  FF+IE8+IE7都能识别!import ...

  5. python 类的私有方法例子

    #coding=utf-8 class Person(object):    id=12    def __init__(self,name):        self.name=name       ...

  6. Zookeeper学习记录(二):使用以及配置

    zookeeper已经介绍了它的原理设计以及实现方式,我们接下来介绍zookeeper的使用方法以及简单配置. 下载 获取Zookeeper的发布包,从Apache下载映像中下载一个最新稳定版本. 单 ...

  7. Struts2快速后台验证 使用

    为了和前台基于JavaScript的开源验证框架RapidValidation使用统一的验证规则, 最大限度的减少重复的后台验证代码, 使用方式简便, 扩展方便. https://blog.csdn. ...

  8. python之路----socketserver模块

    socketserver import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): ...

  9. Notes of Head.First.HTML.and.CSS.2nd.Edition

    What does the web server do? tirelessly waiting for requests from webbrowsers What does the web brow ...

  10. Python3 itchat微信获取好友、公众号、群聊的基础信息

    Python3 itchat微信获取好友.公众号.群聊的基础信息 一.简介 安装 itchat pip install itchat 使用个人微信的过程当中主要有三种账号需要获取,分别为: 好友 公众 ...