Java四种引用的区别?

Java中,对象的引用类型对垃圾回收器的影响非常大。Java中主要有四种类型的引用:强引用、软引用、弱引用和虚引用。

四种引用的区别?

强引用是最强的,如果一个对象具有强引用,那么垃圾回收器绝不会回收它。

当空间不够时才会回收软引用。如果内存充足,即使软引用只是可达的,也不会被回收。软引用通常用于实现内存敏感的缓存

弱引用是一种比软引用更弱的引用类型。当垃圾回收器工作时,无论内存是否充足,只要发现弱引用对象,就会回收它所指向的对象。

注意:软引用是空间不够时回收,而弱引用是在下一次 GC 之前被回收。

虚引用是所有引用类型中最弱的一个,作用是在被回收时可以获得通知。

注意:虚引用和弱引用都是随时被回收,但是虚引用被回收是能够收到通知的。

四种引用的发展历史

在Java的发展历程中,四种类型的引用:强引用、软引用、弱引用和虚引用的引入和使用都有其特定的历史背景和原因。

强引用:强引用是Java语言中最基本的引用类型,从Java诞生之初就存在。强引用是指在程序代码中普遍存在的,类似”Object obj = new Object()”这类的引用,只要强引用还存在,垃圾收集器就永远不会回收掉被引用的对象。

软引用:软引用是在Java 2(即JDK 1.2)引入的,主要用于实现内存敏感的缓存。软引用可以让开发者在内存不足时,让垃圾收集器回收一些还有用但并非必需的对象,从而防止OutOfMemoryError的发生。

弱引用:弱引用也是在Java 2(即JDK 1.2)引入的。弱引用关联的对象只能生存到下一次垃圾回收发生为止,这使得弱引用非常适合用于实现缓存。Java库中的WeakHashMap就是利用弱引用来实现的。

虚引用:虚引用是在Java 2(即JDK 1.2)引入的,它是所有引用类型中最弱的一个。虚引用的主要作用是跟踪对象被垃圾回收器回收的活动,当某个对象被垃圾回收器回收时会收到一个系统通知。

通过这四种引用类型,Java提供了一种灵活的机制,让开发者可以根据实际需求选择合适的引用类型,以达到内存管理和垃圾回收的最优效果。以上就是Java中四种引用类型的发展历史和变迁过程。

强引用是什么?

在Java中,强引用是最常见的引用类型。如果一个对象具有强引用,那么垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。

下面是一个具体的例子:

Object obj = new Object(); // obj是一个强引用

在这个例子中,我们创建了一个新的Object对象,并且用obj变量来引用它。这里的obj就是一个强引用。

只要obj变量还在作用域内,并且我们没有显式地将其设置为null,那么垃圾回收器就不会回收这个Object对象,无论内存是否紧张。

obj = null// 现在垃圾回收器可以回收这个Object对象了

在这个例子中,我们将obj设置为null,这意味着Object对象不再有强引用指向它。因此,垃圾回收器现在可以安全地回收这个Object对象,以便回收内存空间。

这就是Java中强引用的基本概念和使用方法。

弱引用是什么?

在Java中,弱引用是一种引用类型,它比软引用更弱。当JVM进行垃圾回收时,无论内存是否充足,只要发现弱引用对象,JVM都会回收它所指向的对象。弱引用主要用于实现规模可变的、基于哈希表的数据结构,如Google Guava中的WeakHashMap。

下面是一个弱引用的例子:

import java.lang.ref.WeakReference;

public class WeakReferenceExample {
    public static void main(String[] args) {
        // 创建一个强引用
        String strongReference = new String("Strong Reference");

        // 创建一个弱引用
        WeakReference<String> weakReference = new WeakReference<>(strongReference);

        // 清除强引用,此时只剩下弱引用
        strongReference = null;

        // 在内存充足的情况下,可以通过get()方法获取弱引用指向的对象
        System.out.println("Before GC: " + weakReference.get());

        // 强制进行垃圾回收
        System.gc();

        // 如果对象被回收,get()方法会返回null
        System.out.println("After GC: " + weakReference.get());
    }
}

在这个例子中,我们首先创建了一个强引用的字符串对象,然后创建了一个指向这个字符串对象的弱引用。当我们清除强引用后,只剩下弱引用指向字符串对象。在垃圾回收后,弱引用指向的对象被回收,weakReference.get()返回null。

软引用是什么?

在Java中,软引用是一种引用类型,它的特点是在内存不足时,JVM会考虑回收软引用指向的对象。如果内存充足,即使软引用只是可达的,也不会被回收。软引用通常用于实现内存敏感的缓存。

下面是一个软引用的例子:

import java.lang.ref.SoftReference;

public class SoftReferenceExample {
    public static void main(String[] args) {
        // 创建一个强引用
        String strongReference = new String("Strong Reference");

        // 创建一个软引用
        SoftReference<String> softReference = new SoftReference<>(strongReference);

        // 清除强引用,此时只剩下软引用
        strongReference = null;

        // 在内存充足的情况下,可以通过get()方法获取软引用指向的对象
        System.out.println("Before GC: " + softReference.get());

        // 强制进行垃圾回收
        System.gc();

        // 如果对象被回收,get()方法会返回null
        System.out.println("After GC: " + softReference.get());
    }
}

在这个例子中,我们首先创建了一个强引用的字符串对象,然后创建了一个指向这个字符串对象的软引用。当我们清除强引用后,只剩下软引用指向字符串对象。在垃圾回收后,如果内存不足,软引用指向的对象可能被回收,softReference.get()可能返回null。

虚引用是什么?

在Java中,虚引用(PhantomReference)是所有引用类型中最弱的一个。一个持有虚引用的对象,和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用于跟踪对象被垃圾回收器回收的活动,比如清理一些非内存资源。

下面是一个虚引用的例子:

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomReferenceExample {
    public static void main(String[] args) {
        // 创建一个强引用
        String strongReference = new String("Strong Reference");

        // 创建一个引用队列
        ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();

        // 创建一个虚引用,需要传入强引用和引用队列
        PhantomReference<String> phantomReference = new PhantomReference<>(strongReference, referenceQueue);

        // 清除强引用,此时只剩下虚引用
        strongReference = null;

        // 虚引用在任何时候都可能被垃圾回收,回收之后会被加入到引用队列中
        System.gc();

        // 检查引用队列,如果虚引用被垃圾回收,它会被加入到引用队列中
        PhantomReference<String> polledReference = (PhantomReference<String>) referenceQueue.poll();

        // 如果虚引用被垃圾回收,polledReference应该和phantomReference相等
        System.out.println(polledReference == phantomReference);
    }
}

在这个例子中,我们首先创建了一个强引用的字符串对象,然后创建了一个指向这个字符串对象的虚引用。当我们清除强引用后,只剩下虚引用指向字符串对象。在垃圾回收后,虚引用指向的对象被回收,虚引用会被加入到引用队列中。

虚引用实现原理?

虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过查看引用队列,来了解被回收对象的信息。

下面是一个虚引用的例子:

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomReferenceExample {
    public static void main(String[] args) {
        // 创建一个强引用
        String strongReference = new String("Strong Reference");

        // 创建一个引用队列
        ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();

        // 创建一个虚引用,需要传入强引用和引用队列
        PhantomReference<String> phantomReference = new PhantomReference<>(strongReference, referenceQueue);

        // 清除强引用,此时只剩下虚引用
        strongReference = null;

        // 虚引用在任何时候都可能被垃圾回收,回收之后会被加入到引用队列中
        System.gc();

        // 检查引用队列,如果虚引用被垃圾回收,它会被加入到引用队列中
        PhantomReference<String> polledReference = (PhantomReference<String>) referenceQueue.poll();

        // 如果虚引用被垃圾回收,polledReference应该和phantomReference相等
        System.out.println(polledReference == phantomReference);
    }
}

在这个例子中,我们首先创建了一个强引用的字符串对象,然后创建了一个指向这个字符串对象的虚引用。当我们清除强引用后,只剩下虚引用指向字符串对象。在垃圾回收后,虚引用指向的对象被回收,虚引用会被加入到引用队列中。

使用场景

在Java中,强引用、软引用、弱引用和虚引用各自有其特定的使用场景:

  1. 强引用:强引用是最常见的引用类型,如果一个对象具有强引用,那么垃圾回收器绝不会回收它。强引用通常用于大部分场景,例如创建对象、数据存储等。

  2. 软引用:软引用是用来描述一些还有用但并非必需的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。软引用通常用于实现内存敏感的缓存,例如Android中的图片缓存。

  3. 弱引用:弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾回收发生为止。弱引用常常用于Map数据结构中,用来引用键(Key),这样在键不再使用时可以自动被回收。

  4. 虚引用:虚引用是最弱的一种引用关系,它无法通过虚引用来获取对一个对象的真实引用。唯一的用处是当被引用的对象被垃圾回收时收到一个系统通知。虚引用主要用于检测对象是否已从内存中被回收,如用于实现比finalization机制更灵活的回收操作,跟踪对象被垃圾回收器回收的活动,如用于实现非确定性的清理行为等。

以上就是Java中四种引用类型的使用场景。


原文始发于微信公众号(everystep):Java四种引用的区别?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/269636.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!