`
yajie
  • 浏览: 211447 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

java程序员应该知道的两种引用

阅读更多

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错误了。

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

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

引用是关系垃圾回收的。

1
3
分享到:
评论

相关推荐

    java程序员转正ppt

    - **对象理解**:深入理解Java对象的创建,如String的两种初始化方式,以及内存中的变量池、堆和栈的区分。掌握Java中的基本数据类型和复杂数据类型,理解引用的概念。 - **集合框架**:理解String到集合的演变,...

    Java程序员面试笔试宝典-何昊pdf版

    根据提供的文件信息,我们可以推断出这是一本关于Java程序员面试和笔试准备的书籍,作者为何昊。本书可能包含了大量关于Java编程语言的基础知识、高级特性以及与面试相关的技巧和策略等内容。下面将对可能涉及的重要...

    JAVA程序员面试宝典

    JAVA语言提供了两种不同的类型:引用类型和原始类型(或内置类型)。int是JAVA的原始数据类型,而Integer是JAVA为int提供的封装类。JAVA为每个原始类型提供了封装类。 4. 异常处理 异常表示程序运行过程中可能出现...

    SUN JAVA程序员模拟题

    ### SUN JAVA程序员模拟题知识点解析 #### 题目1: JDK组成部分 - **知识点**:JDK(Java Development Kit)组成 - **解析**:JDK主要由以下几个部分组成: - **Java编程语言**:Java编程语言是用于编写Java应用...

    Java程序员面试宝典

    ### Java程序员面试宝典知识点概览 #### 一、基础部分 **1. Java程序的入口** - **知识点:** Java程序必须有一个主类包含`main`方法作为程序的入口。 - **详解:** 每个Java应用程序都必须至少包含一个`main`方法...

    Java程序员基础手册.pdf

    自动类型转换发生在两种类型兼容且目标类型比源类型大的情况下,例如从`int`到`float`的转换。强制类型转换允许开发者显式地将一种类型的值转换为另一种类型,但需谨慎使用,以避免数据损失或错误。编码实践中,推荐...

    2019年最新版修订版Java程序员面试宝典.pdf

    Java程序员面试宝典2019修订版是针对Java开发人员的一份重要的参考资料,涵盖了Java基础知识和一些面试中常见的问题。以下是从文档中提取的与Java相关的知识点: 1. Java面向对象特性:面向对象的三大特性包括封装...

    Java程序员面试题集

    Java程序员面试时,通常会遇到一系列关于语言特性和框架的问题,这些题目旨在考察候选人的基础知识、问题解决能力和实践经验。以下是对这些面试题目的详细解答: 1. **final, finally, finalize的区别**: - `...

    Java程序员面试题

    Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int 是 Java 的原始数据类型,Integer 是 Java 为 int 提供的封装类。Java 为每个原始类型提供了封装类。 4. String 和 StringBuffer 的区别 Java ...

    java程序员面试技巧

    ### Java程序员面试技巧详解 #### 面向对象的四大特征 在Java面试过程中,面试官经常会提问关于面向对象的基本概念及其特征。了解并掌握这些基本概念对于通过面试至关重要。 **1. 抽象** 抽象是指在编程时,只...

    JAVA程序员面试宝典 第4版-欧立奇

    本章将对比这两种技术,并分析它们的优缺点。 - **JVM内存模型**:深入剖析JVM的内存布局,包括堆内存、栈内存等区域的作用及管理方式,以及垃圾回收机制的原理。 - **泛型与集合**:泛型是JAVA5引入的新特性,可以...

    java初级程序员试题

    2. **数据类型**:Java有两大类数据类型——基本数据类型和引用数据类型。基本数据类型包括整型(byte, short, int, long)、浮点型(float, double)、字符型(char)和布尔型(boolean)。引用数据类型则包括类、...

    java程序员面试宝典.txt

    Java中有两种类型的异常:检查型异常(Checked Exception)和运行时异常(Runtime Exception)。检查型异常必须在编译时进行处理,通常通过try-catch块捕获或在方法签名中声明抛出;运行时异常则是在运行时抛出的,...

    java程序员面试题集合

    ### Java程序员面试题集合知识点详解 #### 一、面向对象的四大特征 1. **抽象** 抽象是面向对象编程中的一个重要概念,它指的是在设计阶段仅考虑问题的关键部分,忽略不相关的细节。抽象可以分为两类: - **...

    C_C++程序员Java编程

    在IT行业中,C++和Java是两种非常重要的编程语言,它们各自有着独特的特性和应用场景,同时也存在着一定的交集。对于已经熟悉C或C++的程序员来说,学习Java编程可以拓展其技术栈,增强其在软件开发领域的竞争力。...

    java初级程序员知识笔记

    Java中有两种类型的变量:实例变量和局部变量。实例变量是属于对象的成员变量,用于存储对象的状态。局部变量是方法内部的变量,用于存储临时数据。Java中的方法可以是静态的,也可以是实例方法。静态方法属于类,而...

    2018最新最全JAVA程序员面试题

    - **SessionBean**:主要用于处理业务逻辑,可以分为有状态(Stateful)和无状态(Stateless)两种。 - **Stateful Session Bean**:维护客户端会话状态,适用于需要跟踪客户端交互的应用。 - **Stateless Session ...

Global site tag (gtag.js) - Google Analytics