Java对象引用的访问方式是什么?

news2024/9/17 7:06:47

对象引用

哈喽,大家好🎉,我是世杰

本文我为大家介绍面试官经常考察的**「Java对象引用相关内容」**

照例在开头留一些面试考察内容~~

面试连环call

  1. Java对象引用都有哪些类型?
  2. Java参数传递是值传递还是引用传递? 为什么?
  3. Java对象引用访问方式有哪些?

上一篇文章讲了 JVM 在执行 new 对象的过程中都执行了那些操作。现在我来讲一下创建对象之后的的使用

1. Java对象引用

《Java编程思想》: 每种编程语言都有自己的数据处理方式。有些时候,程序员必须注意将要处理的数据是什么类型。你是直接操纵元素,还是用某种基于特殊语法的间接表示(例如C/C++里的指针)来操作对象。所有这些在 Java 里都得到了简化,一切都被视为对象。因此,我们可采用一种统一的语法。尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“引用”(reference)

Java程序需要通过栈上的引用数据来操作堆上的具体对象。对象的访问方式取决于虚拟机实现,目前主流的访问方式有使用句柄和直接指针两种。

  • 直接指针:指向对象,代表对象的内存地址。
  • 句柄:句柄是一种特殊的指针,可以理解为指向指针的指针,维护指向对象的指针变化,而对象的句柄本身不发生变化

1.1 直接指针

如果使用直接指针访问,那么Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而引用中存储的直接就是对象地址

  • 优势:速度更快,节省了一次指针定位的时间开销。当对象的访问非常频繁,此开销积也可节省非常可观的成本。

img

1.2 句柄

Java堆中划分出一块内存来作为句柄池,引用中存储对象的句柄地址,而句柄中包含了对象实例数据类型数据各自的具体地址信息。

  • 优势:引用中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而引用本身不需要修改
  • 缺点:需要两次指针访问才能访问到对象数据。

img


2. 对象引用类型

在Java中一共有四种引用类型,分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱。

2.1 强引用

强引用是最常见的引用类型。

  • 当我们创建一个对象并将其赋值给一个引用变量时,这个引用就被称为强引用。只要强引用存在,垃圾回收器就不会回收被引用的对象。即使系统内存空间不足,JVM宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的存活对象来解决内存不足问题。
  • 强引用的特性是只要有强引用存在,被引用的对象就不会被垃圾回收。
  • 可以将强引用赋值为 null,这样一来,JVM 就可以适时的回收对象了(注意不是立刻回收)
public class StrongReferenceUsage {

    @Test
    public void stringReference(){
        Object obj = new Object();
    }
}

上面我们new了一个Object对象,并将其赋值给obj,这个obj就是new Object()的强引用。

2.2 软引用

软引用是用来描述一些还有用但并非必需的对象。

  • 对于软引用关联着的对象,在系统将要发生内存溢出异常前,将会把这些对象列进回收范围进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。在Java中,软引用通过java.lang.ref.SoftReference类来实现。

  • 这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。

    @Test
    public void softReference(){
        Object obj = new Object();
        SoftReference<Object> soft = new SoftReference<>(obj);
        obj = null;
        log.info("{}",soft.get());
        System.gc();
        log.info("{}",soft.get());
    }

输出结果:

22:50:43.733 [main] INFO com.flydean.SoftReferenceUsage - java.lang.Object@71bc1ae4
22:50:43.749 [main] INFO com.flydean.SoftReferenceUsage - java.lang.Object@71bc1ae4

可以看到在内存充足的情况下,SoftReference引用的对象是不会被回收的。

2.3 弱引用

弱引用也是用来描述非必需对象的,不过它的强度比软引用更弱一些。

  • 被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收被弱引用的对象。

  • 在Java中,弱引用通过java.lang.ref.WeakReference类来实现。

    @Test
    public void weakReference() throws InterruptedException {
        Object obj = new Object();
        WeakReference<Object> weak = new WeakReference<>(obj);
        obj = null;
        log.info("{}",weak.get());
        System.gc();
        log.info("{}",weak.get());
    }

输出结果:

22:58:02.019 [main] INFO com.flydean.WeakReferenceUsage - java.lang.Object@71bc1ae4
22:58:02.047 [main] INFO com.flydean.WeakReferenceUsage - null

可以看到即便在内存充足的情况下,WeakReference引用的对象也被回收了。

2.4 虚引用

虚引用是最弱的一种引用关系。

  • 一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例
  • 为一个对象设置虚引用的唯一目的就是能在这个对象被收集器回收时收到一个系统通知
  • 在Java中,虚引用通过java.lang.ref.PhantomReference类来实现。
  • 虚引用必须和引用队列(ReferenceQueue)联合使用

PhantomReference的作用是跟踪垃圾回收器收集对象的活动,在GC的过程中,如果发现有PhantomReference,GC则会将引用放到ReferenceQueue中,由程序员自己处理,当程序员调用ReferenceQueue.pull()方法,将引用队列中的对象引用移除之后,Reference对象会变成Inactive状态,意味着被引用的对象可以被回收了。

@Slf4j
public class PhantomReferenceUsage {

    @Test
    public void usePhantomReference(){
        ReferenceQueue<Object> rq = new ReferenceQueue<>();
        Object obj = new Object();
        PhantomReference<Object> phantomReference = new PhantomReference<>(obj,rq);
        obj = null;
        log.info("{}",phantomReference.get());
        System.gc();
        Reference<Object> r = (Reference<Object>)rq.poll();
        log.info("{}",r);
    }
}

输出结果:

07:06:46.336 [main] INFO com.flydean.PhantomReferenceUsage - null
07:06:46.353 [main] INFO com.flydean.PhantomReferenceUsage - java.lang.ref.PhantomReference@136432db

我们看到get的值是null,而GC过后,poll是有值的。

因为PhantomReference引用的是需要被垃圾回收的对象,所以在类的定义中,get一直都是返回null:

    public T get() {
        return null;
    }

『总结』

  • 强引用是最常见的类型,但如果内存空间不足,可能会导致OutOfMemoryError错误。
  • 软引用的对象在系统内存即将溢出时会被回收,适用于缓存等情况。
  • 弱引用的对象无论当前内存空间足够与否都会被回收,适用于实现对象的单例模式等。
  • 虚引用的主要目的是为了能收到系统通知,以便在对象被回收时进行相应的处理。

在程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,这是因为软引用可以加速 JVM 对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OOM)等问题的产生。


3. 值传递 vs 引用传递

3.1 定义

  1. 值传递:方法参数传入的是参数的备份,对参数的修改并不会影响本身
  2. 引用传递:方法参数传入的都是参数的引用,对参数的修改会影响本身

Java的参数传递是值传递还是引用传递?

先说结论:Java本质上都是值传递

3.2 Java对象类型

说到值传递和引用传递我们不得不提到两个概念:值类型和引用类型

基本类型是值类型。JVM赋值时,直接在栈上生成值

java_value_type

类、接口、数组、对象、基本类型的包装类都是引用类型。JVM赋值时,在栈上生成引用,在堆中生成数据

java_reference_type

3.3 为什么?

先看一段代码

    @Test
    public void testReference() {
        Base base = new Base();
        base.setName("main");
        set2(base);
        System.out.println(base.getName());
    }

    private void set1(Base base) {
        base.setName("set1");
    }

    private void set2(Base base) {
        base = new Base();
        base.setName("set2");
    }

上述的方法,调用set1的执行结果是【set1】,调用set2的执行结果是【main】

由此可以看出,方法入参传入的都是副本

  1. 当是基本类型时,传入的是基本类型的拷贝副本,修改基本类型的【入参】并不会影响【实参】
  2. 当是引用类型时,传入的引用类型依旧是拷贝副本,但是此时的副本是拷贝地址,因此修改入参会影响到实现的值,因此入参和实参的指向都是堆中同一个内存区域,例如set1方法。但当为入参重新赋值一个新的地址,并在修改此地址指向的内存区域,就不会影响实参中的值,例如set2方法。

所以Java是值传递


参考文章

  1. https://mp.weixin.qq.com/s/r5cMTmQjNwYwiX7pLx_52Q

  2. JAVA对象的创建及内存分配详解

  3. 对象和引用

  4. 理解java对象的引用

  5. 一文读懂java中的Reference和引用类型

  6. 这一次,彻底解决Java的值传递和引用传递

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1916899.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解释 C 语言中的递归函数

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; &#x1f4d9;C 语言百万年薪修炼课程 通俗易懂&#xff0c;深入浅出&#xff0c;匠心打磨&#xff0c;死磕细节&#xff0c;6年迭代&#xff0c;看过的人都说好。 文章目…

各向异性含水层中地下水三维流基本微分方程的推导

各向异性含水层中地下水三维流基本微分方程的推导 参考文献&#xff1a; [1] 刘欣怡,付小莉.论连续性方程的推导及几种形式转换的方法[J].力学与实践,2023,45(02):469-474. 文章链接 水均衡的基本思想&#xff1a; ∑ 流 入 − ∑ 流 出 Δ V \sum 流入-\sum 流出\Delta V ∑…

【系统架构设计师】九、软件工程(软件测试)

目录 八、软件测试 8.1 测试分类 8.2 静态方法 8.2.1 静态测试 8.2.2 动态测试 8.2.3 自动化测试 8.3 测试阶段 8.3.1 单元测试 8.3.2 集成测试 8.3.3 确认测试 8.3.4 系统测试 8.3.5 性能测试 8.3.6 验收测试 8.3.7 其他测试 8.4 测试用例设计 8.4.1 黑…

使用 Python 绘制美国选举分级统计图

「AI秘籍」系列课程&#xff1a; 人工智能应用数学基础 人工智能Python基础 人工智能基础核心知识 人工智能BI核心知识 人工智能CV核心知识 如何创建美国选举结果的时间序列分级统计图 数据地址为源地址&#xff0c;如果失效请与我联系。 2024 年美国大选将至&#xff0c;…

算法通关:004_1选择排序

代码一定要自己手敲理解 public class _004 {//选择排序&#xff0c;冒泡排序&#xff0c;插入排序//交换public static void swap(int[] arr,int i ,int j){int temp arr[i];arr[i] arr[j];arr[j] temp;}//选择排序public static void selectSort(int[] arr){if(arr null…

C++ | Leetcode C++题解之第225题用队列实现栈

题目&#xff1a; 题解&#xff1a; class MyStack { public:queue<int> q;/** Initialize your data structure here. */MyStack() {}/** Push element x onto stack. */void push(int x) {int n q.size();q.push(x);for (int i 0; i < n; i) {q.push(q.front());…

LabVIEW实现LED显示屏视觉检测

为了满足LED显示屏在生产过程中的严格质量检测需求&#xff0c;引入自动化检测系统是十分必要的。传统人工检测方式存在检测强度高、效率低、准确性差等问题&#xff0c;自动化检测系统则能显著提高检测效率和准确性。视觉检测系统的构建主要包含硬件和软件两个部分。 视觉系统…

JDK中不能继承的类:final类的作用与意义

JDK中不能继承的类&#xff1a;final类的作用与意义 1、 为什么要用final类&#xff1f;2、JDK中有哪些final类&#xff1f;3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java编程中&#xff0c;有些类被标记为final&#xff0c…

前端面试题47(在动态控制路由时,如何防止未授权用户访问受保护的页面?)

在Vue中&#xff0c;防止未授权用户访问受保护页面通常涉及到使用路由守卫&#xff08;Route Guards&#xff09;。路由守卫允许你在路由发生改变前或后执行一些逻辑&#xff0c;比如检查用户是否已登录或者有访问某个页面的权限。下面是一些常见的路由守卫类型及其使用方式&am…

MapReduce底层原理详解:大案例解析(第32天)

系列文章目录 一、MapReduce概述 二、MapReduce工作机制 三、Map&#xff0c;Shuffle&#xff0c;reduce阶段详解 四、大案例解析 文章目录 系列文章目录前言一、MapReduce概述二、MapReduce工作机制1. 角色与组件2. 作业提交与执行流程1. 作业提交&#xff1a;2. Map阶段&…

IntelliJ IDEA社区版在Windows电脑中的下载、安装方法

本文介绍IntelliJ IDEA软件Community&#xff08;社区版&#xff09;在Windows操作系统中的下载、安装、运行与使用方法。 IntelliJ IDEA软件是一款由JetBrains公司开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;主要用于Java语言的开发&#xff0c;但同时也支持其…

面试经验之谈

优质博文&#xff1a;IT-BLOG-CN ​通常面试官会把每一轮面试分为三个环节&#xff1a;① 行为面试 ② 技术面试 ③ 应聘者提问 行为面试环节 面试开始的5~10分钟通常是行为面试的时间&#xff0c;面试官会参照简历和你的自我介绍了解应聘者的过往经验和项目经历。由于面试官…

读书笔记-Java并发编程的艺术-第4章(Java并发编程基础)-第4节(线程应用实例)

文章目录 4.4 线程应用实例4.4.1 等待超时模式4.4.2 一个简单的数据库连接池示例4.4.3 线程池技术及其示例4.4.4 一个基于线程池技术的简单 Web 服务器 4.4 线程应用实例 4.4.1 等待超时模式 开发人员经常会遇到这样的方法调用场景&#xff1a;调用一个方法时等待一段时间(一…

postgres 的dblink使用,远程连接数据库

一.安装下载 dblink create extension if not exists dblink 查看是否已经安装 select * from pg_extension;二.运行&#xff0c;查询数据 其中&#xff0c;第一个参数是dblink名字&#xff0c;也可以是连接字符串。 第二个参数是要执行的SQL查询语句。AS子句用于指定返回结…

网桥与以太网交换机:功能与区别解析

在传统的共享式局域网中&#xff0c;所有站点共享一个公共的传输媒体。随着局域网规模的扩大、网络中站点数目的不断增加&#xff0c;这样的网络通信负载加重&#xff0c;网络效率急剧下降。随着技术的发展、交换技术的成熟和成本的降低&#xff0c;具有更高性能的交换式局域网…

kali安装vulhub遇到的问题及解决方法(docker及docker镜像源更换)

kali安装vulhub&#xff1a; 提示&#xff1a;项目地址 https://github.com/vulhub/vulhub 项目安装&#xff1a; git clone https://github.com/vulhub/vulhub.git 安装docker 提示&#xff1a;普通用户请使用sudo&#xff1a; 首先安装 https 协议、CA 证书 apt-get in…

Apache Flink 运行时架构

Flink 运行时架构 Flink整个系统由两个主要部分组成JobManager和TaskManager&#xff0c;Flink架构也遵循Master-Slave架构设计原则&#xff0c;JobManager为Master节点&#xff0c;TaskManager为worker&#xff08;Slave&#xff09;节点&#xff0c;所有组件之间通讯都是借助…

内容协商源码解析与自定义 MessageConverter

目录 内容协商 1、引入xml依赖 2、postman分别测试返回json和xml 3、开启浏览器参数方式内容协商功能 4、内容协商原理 5、自定义 MessageConverter 综上 内容协商 根据客户端接收能力不同&#xff0c;返回不同媒体类型的数据。 若客户端无法解析服务端返回的内容&#…

CinemachineBrain的属性简介

CinemachineBrain的属性简介 CinemachineBrain是Unity Cinemachine的核心组件&#xff0c;它和Camera组件挂载在一起&#xff0c;监控场景中所有的virtual camera。CinemachineBrain在inspector中暴露的属性如下&#xff1a; Live Camera和Live Blend分别表示当前active的virtu…