广告
返回顶部
首页 > 资讯 > 精选 >Java的引用类型及使用场景是什么
  • 614
分享到

Java的引用类型及使用场景是什么

2023-06-14 09:06:57 614人浏览 安东尼
摘要

这篇文章将为大家详细讲解有关Java的引用类型及使用场景是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。每种编程语言都有自己操作内存中元素的方式,例如在 C 和 c++ 里是通过指针,而在 Java

这篇文章将为大家详细讲解有关Java的引用类型及使用场景是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

每种编程语言都有自己操作内存中元素的方式,例如在 C 和 c++ 里是通过指针,而在 Java 中则是通过“引用”。在 jdk.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种。

1. 强引用(Strong Reference)

强引用类型,是我们最常讲的一个类型,我们先看一个例子:

package cn.bridgeli.demo.reference; public class User {     @Override    protected void finalize() throws Throwable {        super.finalize();        System.out.println("finalize");    } } package cn.bridgeli.demo.reference; import org.junit.Test; public class StrongReferenceTest {     @Test    public void testStrongReference() {        User user = new User();        user = null;        System.GC();        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

我们都知道当一个实例对象具有强引用时,垃圾回收器不会回收该对象,当内存不足时,宁愿 OOM,也就是抛出 OutOfMemeryError 异常也不会回收强引用的对象,因为 JVM 认为强引用的对象是用户正在使用的对象,它无法分辨出到底该回收哪个,强行回收有可能导致系统严重错误。但是当对象被赋值为 null 之后,会被回收,并且会执行对象的 finalize 函数,此时我们可以通过该函数拯救自己,但是有两点需要注意一个是只能拯救一次,当再次被垃圾回收的时候就不能拯救了,另一个就是有事没事千万不要重写次函数,本例只是为了说明问题重写了此函数,如果在工作中误重写了此函数,可能会导致垃圾不能回收,最终 OOM,另外有熟悉 GC 的同学没?猜一下我为什么要 sleep 一下?

2. 软引用(Soft Reference)

在我刚学 Java 的时候,并不知道怎么使用软引用,那时候只知道强引用,其实是通过 java.lang.ref.SoftReference 类来使用软引用的,为了说明软引用,我们先看一个例子:

package cn.bridgeli.demo.reference; import org.junit.Test; import java.lang.ref.SoftReference; public class SoftReferenceTest {     @Test    public void testSoftReference() {        SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);        System.out.println(softReference.get());         System.gc();         try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }         System.out.println(softReference.get());         byte[] bytes = new byte[1024 * 1024 * 12];         System.out.println(softReference.get());    }}

除了通过 get 方法获取我们的软引用对象之外,运行结果和强引用类型并没有什么区别是吧?结果和我们想的一样,但是别着急,加一个启动参数再试试:

-Xms20m -Xmx20m

我们都知道,这两个参数是控制 JVM 启动的时候堆的最大值和最小值的,这里面我们设置的最大值和最小值都是 20M,按照强引用的逻辑,我们一共申请了 22M 的空间,应该 OOM 才对,事实证明并没有,通过打印语句证明,我们的软引用被回收了,所以软引用的特点是:在内存足够的时候,软引用对象不会被垃圾回收器回收,只有在内存不足时,垃圾回收器则会回收软引用对象,当然回收了软引用对象之后仍然没有足够的内存,这时同样会抛出内存溢出异常。

看了软引用的特点,我们很容易想到软引用的使用场景:缓存。记得刚工作的时候,有个同事给我说,他做 Android,有一个加载图片的应用,特麻烦,会 OOM,其实使用软引用应该很轻松的能解决这个问题。

3. 弱引用(Weak Reference)

弱引用是通过 java.lang.ref.WeakReference 类来实现的,同样我们也先看一个例子:

package cn.bridgeli.demo.reference; import org.junit.Test; import java.lang.ref.WeakReference; public class WeakReferenceTest {     @Test    public void testWeakReference() {        WeakReference<User> weakReference = new WeakReference<>(new User());        System.out.println(weakReference.get());         System.gc();         try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }         System.out.println(weakReference.get());    }}

通过例子我们可以看到,弱引用是一种比软引用更弱的引用类型:在系统 GC 时,只要发现弱引用,不管系统堆空间是否足够,都会将对象进行回收。看到这里可能会有同学有疑问,GC 什么时候启动,除了我们显示调用外,我们并不能控制(其实就算我们显示调用,GC 也可能不会立即执行),而且 GC 之后,弱引用立即被回收,引用不到了,那么这个类型有什么用呢?其实这个类型还真有大用,我们鼎鼎大名的 ThreadLocal 类就是借助于这个类实现的,所以当你使用 ThreadLocal 的时候,就已经在使用弱类型了,我之前曾经写过关于 ThreadLocal 的文章,但是当时理解不是很准确,不过说明的例子是没有问题的,所以还有一定的参考价值,后面看看啥时候有机会重写一篇关于 ThreadLocal 的文章,详细说说这个类。

另外除了 ThreadLocal 类外还有一个类值得说一下,那就是 java.util.WeakHashMap 类,见名知意,我们就可以猜到这个类的特点。同样通过一个例子说明一下:

package cn.bridgeli.demo.reference; import org.junit.Test; import java.util.Map;import java.util.WeakHashMap; public class WeakHashMapTest {     @Test    public void testWeakHashMap() {        Map map = new WeakHashMap<String, Object>();        for (int i = 0; i < 10000; i++) {            map.put("key" + i, new byte[i]);        } //        Map map = new HashMap<String, Object>();//        for (int i = 0; i < 10000; i++) {//            map.put("key" + i, new byte[i]);//        }    }}

记得启动的时候设置一下,设置一下启动的时候堆的大小,不要设置太大,可以看出区别。

4. 虚引用(Phantom Reference)

通过前面的例子,我们可以看到引用强度是越来越弱的,所以虚引用是最弱的一种引用类型,到底有多弱呢,我们同样通过一个例子来看,需要说明的是,虚引用是通过 java.lang.ref.PhantomReference 类实现的。

package cn.bridgeli.demo.reference; import org.junit.Test; import java.lang.ref.PhantomReference;import java.lang.ref.Reference;import java.lang.ref.ReferenceQueue;import java.util.ArrayList;import java.util.List; public class PhantomReferenceTest {     ReferenceQueue referenceQueue = new ReferenceQueue();    List<Object> list = new ArrayList<>();     @Test    public void testPhantomReference() {        PhantomReference<Object> phantomReference = new PhantomReference<>(new Object(), referenceQueue);        System.out.println(phantomReference.get());         new Thread(() -> {            while (true) {                Reference reference = referenceQueue.poll();                if (null != reference) {                    System.out.println("============ " + reference.hashCode() + " ============");                }            }        }).start();         new Thread(() -> {            while (true) {                list.add(new byte[1024 * 1024 * 10]);            }        }).start();         try {            Thread.sleep(500);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

我们看到了是什么?虽然软引用和弱引用也很弱,但是我们还是可以通过 get 方法获取到我们的引用对象,但是虚引用却不行,点进去看一下源码,我们可以看到虚引用的 get 方法,直接返回 null,也就是我们直接拿不到虚引用对象,那么这个类型又有什么使用场景呢?其实这个类型就不是给我们普通程序员使用的,在 io、堆外内存中有使用,所以对于我们普通程序员来说,了解到存在这个类型,另外通过上面的例子,我们还可以看到:当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在垃圾回收后,销毁这个对象,将这个虚引用加入引用队列。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。那么我们就可以在程序中发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些必要的行动。

关于“Java的引用类型及使用场景是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: Java的引用类型及使用场景是什么

本文链接: https://www.lsjlt.com/news/269577.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java的引用类型及使用场景是什么
    这篇文章将为大家详细讲解有关Java的引用类型及使用场景是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。每种编程语言都有自己操作内存中元素的方式,例如在 C 和 C++ 里是通过指针,而在 Java ...
    99+
    2023-06-14
  • 详解Java的引用类型及使用场景
    目录1. 强引用(Strong Reference)2. 软引用(Soft Reference)3. 弱引用(Weak Reference)4. 虚引用(Phantom Refere...
    99+
    2022-11-12
  • Java中的引用类型和使用场景详细
    目录1、强引用2、软引用3、弱引用4、弱引用的使用场景5、虚引用Java中的引用类型有哪几种? Java中的引用类型分成 强引用 , 软引用 , 弱引用 , 虚引用 。 1、强...
    99+
    2022-11-12
  • Redis数据类型及应用场景是什么
    小编给大家分享一下Redis数据类型及应用场景是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1. string类型1-1 ...
    99+
    2022-10-18
  • PHP中数据类型的分类及其应用场景是什么?
    PHP是一种广泛使用的服务器端编程语言。在PHP中,数据类型是程序员必须了解的一个重要概念。在本文中,我们将讨论PHP中的数据类型及其应用场景。 PHP中的数据类型可以分为以下几类: 整数类型(Integer) 浮点数类型(Float) ...
    99+
    2023-11-08
    日志 数据类型 apache
  • java SPI的使用场景是什么
    本文小编为大家详细介绍“java SPI的使用场景是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“java SPI的使用场景是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。概念SPI是服务提供界面,JD...
    99+
    2023-06-30
  • Java函数数据类型在Apache中的应用场景是什么?
    Apache是一个开源的、跨平台的Web服务器,也是目前最流行的Web服务器之一。它的核心是Apache HTTP Server,是一个高性能的Web服务器,支持多种操作系统和编程语言。Java是一种面向对象的编程语言,常用于Web开发、...
    99+
    2023-08-16
    函数 数据类型 apache
  • Redis多种数据类型以及使用场景
    SDS简单动态字符串 struct sdshdr { // 记录buf数组中已使用字节的数量 // 等于SDS所保存字符串的长度 int len; // 记录buf数组中未使用字节的数量 int free; // 字节数组,用于保存字符...
    99+
    2014-11-22
    Redis多种数据类型以及使用场景
  • Redis数据类型及使用场景有哪些
    这篇文章主要介绍“Redis数据类型及使用场景有哪些”,在日常操作中,相信很多人在Redis数据类型及使用场景有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis数...
    99+
    2022-10-19
  • 谈谈VPN是什么、类型、使用场景、工作原理
    作者:Insist-- 个人主页:insist--个人主页 作者会持续更新网络知识和python基础知识,期待你的关注 前言 本文将讲解VPN是什么、以及它的类型、使用场景、工作原理。 目录 一、VPN是什么? 二、VPN的类型 ...
    99+
    2023-08-31
    运维 网络
  • java四种引用类型是什么
    Java中有四种引用类型,它们分别是:1. 强引用(Strong Reference):最常见的引用类型,只要一个对象有强引用与之关...
    99+
    2023-09-28
    java
  • java中@Configuration使用场景是什么
    这篇文章主要讲解了“java中@Configuration使用场景是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中@Configuration使用场景是什么”吧!一、简单介绍@...
    99+
    2023-07-05
  • JSON Schema概念及使用场景是什么
    本篇内容介绍了“JSON Schema概念及使用场景是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.什么是JSON Sch...
    99+
    2023-07-02
  • RabbitMQ原理以及使用场景是什么
    本篇文章给大家分享的是有关RabbitMQ原理以及使用场景是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一. RabbitMQ 简介MQ...
    99+
    2022-10-19
  • java反射机制及常用应用场景是什么
    这篇文章主要介绍“java反射机制及常用应用场景是什么”,在日常操作中,相信很多人在java反射机制及常用应用场景是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java反射机制及常用应用场景是什么”的疑...
    99+
    2023-06-29
  • MySQL 中 DATETIME 和 TIMESTAMP 时间类型的区别及使用场景
    MySQL的日期类型简介 在 MySQL 中有两种存储时间的数据类型 DATETIME 和 TIMESTAMP,它们在数据库实际应用中,各有各的优势和劣势。 一. DATETIME 和 TIMESTAMP 的相同点 两个数据类型存储时...
    99+
    2023-09-01
    mysql sql 数据库
  • Redis的使用场景是什么
    这篇文章主要介绍“Redis的使用场景是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Redis的使用场景是什么”文章能帮助大家解决问题。Redis常用命令总结:包括时间复杂度总结与具体数据类型...
    99+
    2023-06-02
  • 索引函数在 Java 中的实际应用场景是什么?
    在 Java 中,索引函数是一个重要的数据结构,它可以提高数据检索的效率。索引函数是一种数据结构,它可以将数据表中的每个记录与一个索引值相对应,这个索引值可以是数据表中的一个属性或多个属性的组合。当我们需要检索数据时,只需要查询索引表,就...
    99+
    2023-09-02
    索引 函数 api
  • MySQL中的数据类型及其应用场景介绍
    MySQL是一种常见的关系型数据库管理系统,广泛应用于各种系统和应用程序中。在MySQL中,数据以不同的数据类型存储在表中。本文将介绍MySQL中常见的数据类型及其应用场景,并附有代码示例。一、整数类型整数类型(INT):用于存储正负整数值...
    99+
    2023-10-22
    适用于表示年龄 数量等整数值) 适用于表示用户名
  • RabbitMQ使用场景是什么
    这篇文章主要介绍“RabbitMQ使用场景是什么”,在日常操作中,相信很多人在RabbitMQ使用场景是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”RabbitMQ使用场景是什么”的疑惑有所帮助!接下来...
    99+
    2023-06-26
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作