Java中的对象——生命周期详解
1. 对象的创建
1.1 使用 new 关键字
执行过程:当使用 new 关键字创建对象时,JVM 会为新对象在堆内存中分配一块空间,并调用对应的构造器来初始化对象。
示例代码:
MyClass obj = new MyClass();
内存变化:JVM 在堆内存中分配空间,所有的成员变量会被初始化为默认值(如整数为 0,引用类型为 null)。构造器会被调用以执行任何自定义初始化逻辑。
关键操作:
- 构造器调用:如果
MyClass有构造器,JVM 会执行这个构造器来设置对象的初始状态。
特点:这种方式是最常用的对象创建方式,类型在编译期已确定,确保了编译时的类型安全。
1.2 反射
执行过程:使用反射可以在运行时创建对象。反射机制通过类的 Class 对象来获取构造器并实例化对象。
示例代码:
MyClass obj = MyClass.class.getDeclaredConstructor().newInstance();
内存变化:与 new 关键字相同,JVM 在堆内存中为新对象分配空间,构造器被调用来初始化对象。
关键操作:
- 无参构造器调用:使用
newInstance()方法时,要求类中有无参构造器,否则会抛出异常。
特点:反射提供了更大的灵活性,能够在运行时创建对象,适合框架或需要动态实例化的场景,但性能稍差,并且缺乏编译时类型安全。
1.3 克隆
执行过程:使用 clone() 方法可以复制一个已有对象的状态,创建一个新的副本。为此,类必须实现 Cloneable 接口。
示例代码:
MyClass obj2 = (MyClass) obj1.clone();
内存变化:JVM 在堆内存中为新对象分配空间,所有简单字段(如整数)会按值复制,而引用字段(如对象引用)将复制指向原对象的引用。
关键操作:
- 浅拷贝:对于简单类型,字段值直接复制;对于引用类型,复制的是引用,意味着两个对象共享同一内存地址。
特点:克隆适合于需要对象副本的场景,但可能导致修改共享字段时的意外行为。使用时需谨慎处理引用类型字段。
1.4 反序列化
执行过程:通过从字节流中还原对象来创建实例。对象必须实现 Serializable 接口,以便能够序列化和反序列化。
示例代码:
ObjectInputStream in = new ObjectInputStream(new FileInputStream("file.obj")); MyClass obj = (MyClass) in.readObject();
内存变化:JVM 在堆内存中分配空间,并将存储在字节流中的对象状态还原至该空间。
关键操作:
- 序列化和反序列化:在对象被序列化时,其状态被转换为字节流,反序列化时则从字节流中恢复原状态。
特点:适用于数据持久化或网络传输,能够保存和恢复对象的状态,但需要确保类的兼容性。
2. 对象的使用
使用过程:一旦对象被创建,可以通过其引用来访问成员变量或调用方法。这一阶段不同创建方式的对象在使用上没有显著区别。
示例代码:
obj.fieldName = 10;
// 修改字段值
System.out.println(obj.fieldName);
// 访问字段值
obj.someMethod();
// 调用方法
变化情况:修改字段值时,内存中实际存储的内容会发生变化,但对象本身的存储位置保持不变。方法调用可能会改变对象的状态。
特点:所有通过不同方式创建的对象在这一阶段都可以直接进行操作,方法调用可以实现特定功能,灵活多样。
3. 变为不可达
变为不可达的过程:对象在没有任何引用指向它时,便变为不可达,等待垃圾回收。这可以通过多种方式实现。
3.1 引用置空
obj = null; // 解除对对象的引用
变化情况:此时对象不再被任何变量引用,成为不可达对象,等待垃圾回收。
3.2 超出作用域
void someMethod() { MyClass obj = new MyClass(); // obj是局部变量
}
// obj在方法结束后不可达
变化情况:当方法执行结束,局部变量obj超出作用域,对象也随之变为不可达。
3.3 循环引用
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
obj1.next = obj2; // obj1引用obj2
obj2.next = obj1; // obj2引用obj1
变化情况:即使存在相互引用,如果没有外部引用,JVM会识别并回收这两个对象。
特点:所有这些方式都导致对象进入不可达状态,准备等待垃圾回收。
4. 垃圾回收
过程:一旦对象变为不可达,JVM的垃圾回收器会在合适的时候回收其占用的内存,确保有效的内存管理。
4.1 标记
在垃圾回收阶段,JVM会从根对象开始遍历,标记所有可达对象。
4.2 清除
清除阶段会释放未被标记的对象所占用的内存,确保垃圾对象被正确回收。
4.3 压缩
JVM可能会在清除阶段后移动存活对象,以避免内存碎片,确保内存的高效利用。
特点:垃圾回收是自动管理的,用户无需手动释放内存,大大减轻了内存管理的负担。
5. 对象的销毁
当对象被垃圾回收后,JVM会释放其占用的内存。销毁对象时可以执行一些清理操作。
5.1 finalize() 方法
示例代码:
protected void finalize() { System.out.println("Object is being destroyed");
}
变化情况:finalize() 方法会在对象被回收前调用,但不保证一定会执行,可能导致资源未被及时释放。
特点:由于其不确定性,不推荐在现代Java中使用,可能影响性能。
5.2 AutoCloseable 接口
示例代码:
try (MyClass obj = new MyClass()) { obj.doSomething();
} // 自动调用 obj.close() 方法
变化情况:在资源使用结束后,自动调用 close() 方法,确保及时释放资源。
特点:这是管理资源(如文件、数据库连接)的一种更好方式,能够明确地控制资源释放的时机。
对比总结
-
对象创建
- 方式:
new关键字:最常用的创建方式,确保编译期的类型安全。- 反射:动态创建对象,适合框架,灵活但性能略低。
- 克隆:复制已有对象,适用于需要保留状态的场景,但仅适用于简单字段。
- 反序列化:从字节流恢复对象,适合持久化和网络传输,但要求类兼容性。
- 特点:每种创建方式都在堆内存中分配空间并调用构造器,适用场景和灵活性不同。
- 方式:
-
对象使用
- 对象在使用阶段通过引用访问成员变量和调用方法。所有创建方式的对象在使用上没有显著差异,均可以进行字段操作和方法调用。
-
变为不可达
- 对象进入不可达状态时,无论是通过引用置空、超出作用域,还是循环引用,都会使得对象等待垃圾回收。所有这些方式的结果是相同的,即对象失去引用。
-
垃圾回收
- 垃圾回收是自动进行的,包括标记、清除和压缩过程。所有不可达对象都将被回收,确保内存的有效利用和自动管理,用户无需手动干预。
-
对象销毁
- 销毁过程主要涉及内存释放:
finalize():在对象被回收前调用,执行不确定,不推荐使用。AutoCloseable:现代Java中优先采用的资源管理方式,确保及时释放资源,适合文件和数据库连接等需要手动关闭的资源。
- 特点:销毁机制确保了在对象生命周期结束后,相关资源得到妥善管理,避免内存泄漏。
- 销毁过程主要涉及内存释放:
Java的对象生命周期管理机制通过自动垃圾回收和灵活的创建方式,使得开发者能够专注于业务逻辑,而无需过多担心内存管理的复杂性。不同的创建和使用方式提供了灵活性与选择,使得Java在开发大规模应用时具备了高效和安全的内存管理特性。在现代Java中,使用AutoCloseable接口进行资源管理已成为最佳实践,确保了资源的及时释放和更好的内存使用效率。
相关文章:
Java中的对象——生命周期详解
1. 对象的创建 1.1 使用 new 关键字 执行过程:当使用 new 关键字创建对象时,JVM 会为新对象在堆内存中分配一块空间,并调用对应的构造器来初始化对象。 示例代码: MyClass obj new MyClass(); 内存变化:JVM 在堆…...
vue文件报Cannot find module ‘webpack/lib/RuleSet‘错误处理
检查 Node.js 版本:这个问题可能与 Node.js 的版本有关。你可以尝试将 Node.js 的版本切换到 12 或更低。如果没有安装 nvm(Node Version Manager),可以通过以下命令安装: curl -o- https://raw.githubusercontent.co…...
第 6 章 机器人系统仿真
对于ROS新手而言,可能会有疑问:学习机器人操作系统,实体机器人是必须的吗?答案是否定的,机器人一般价格不菲,为了降低机器人学习、调试成本,在ROS中提供了系统的机器人仿真实现,通过仿真&#x…...
爬虫——scrapy的基本使用
一,scrapy的概念和流程 1. scrapy的概念 Scrapy是一个Python编写的开源网络爬虫框架。它是一个被设计用于爬取网络数据、提取结构性数据的框架。 框架就是把之前简单的操作抽象成一套系统,这样我们在使用框架的时候,它会自动的帮我们完成很…...
聚类分析算法——K-means聚类 详解
K-means 聚类是一种常用的基于距离的聚类算法,旨在将数据集划分为 个簇。算法的目标是最小化簇内的点到簇中心的距离总和。下面,我们将从 K-means 的底层原理、算法步骤、数学基础、距离度量方法、参数选择、优缺点 和 源代码实现 等角度进行详细解析。…...
【Sublime Text】设置中文 最新最详细
在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。 【Sublime Text】设置中文 最新最详细 开…...
C++学习路线(二十四)
静态成员函数 类的静态方法: 1.可以直接通过类来访问【更常用】,也可以通过对象(实例)来访问。 2.在类的静态方法中,不能访问普通数据成员和普通成员函数(对象的数据成员和成员函数) 1)静态数据成员 可以直接访问“静态数据成员”对象的成…...
MySQL-存储过程/函数/触发器
文章目录 什么是存储过程存储过程的优缺点存储过程的基本使用存储过程的创建存储过程的调用存储过程的删除存储过程的查看delimiter命令 MySQL中的变量系统变量用户变量局部变量参数 if语句case语句while循环repeat循环loop循环游标cursor捕获异常并处理存储函数触发器触发器概…...
前端页面样式没效果?没应用上?
当我们在开发项目时会有很多个页面、相同的标签,也有可能有相同的class值。样式设置的多了,分不清哪个是当前应用的。我们可以使用网页的开发者工具。 在我们开发的网页中按下f12或: 在打开的工具中我们可以使用元素选择器,单击我…...
Mac apache配置cgi环境-修改httpd.conf文件、启动apache
Mac自带Apache,配置CGI,分以下几步: 找到httpd.conf。打开终端,编辑以下几处,去掉#或补充内容。在这个路径下写一个测试文件.py格式的,/Library/WebServer/CGI-Executables,注意第一行的python…...
多厂商的实现不同vlan间通信
Cisco单臂路由 Cisco路由器配置 -交换机配置 -pc配置 华三的单臂路由 -路由器配置 -华三的接口默认是打开的 -pc配置及ping的结果 -注意不要忘记配置默认网关 Cisco-SVI -交换机的配置 -创建vlan -> 设置物理接口对应的Acess或Trunk -> 进入vlan接口,打开接…...
sh与bash的区别
sh与bash的区别 结论:对于一般开发者,没有区别;对于要使脚本兼容较老系统,或者兼容其他shell(如ksh,dash),那么意义可能很重大,要确保自己代码没有bash扩展的特性。 区…...
D48【python 接口自动化学习】- python基础之类
day48 练习:开发自动咖啡(上) 学习日期:20241025 学习目标:类 -- 62 小试牛刀:如何开发自动咖啡机?(上) 学习笔记: 案例解析 定义类 定义属性和方法 clas…...
PostgreSQL(WINDOWS)下载、安装、简单使用
下载 PostgreSQL: Downloads PostgreSQL: Windows installers EDB: Open-Source, Enterprise Postgres Database Management 安装 注意密码要方便自己使用,不能忘记。 打开pgAdmin,输入密码 新建数据库 打开命令工具 新建表...
Git的初次使用
一、下载git 找淘宝的镜像去下载比较快 点击这里 二、配置git 1.打开git命令框 2.设置配置 git config --global user.name "你的用名"git config --global user.email "你的邮箱qq.com" 3.制作本地仓库 新建一个文件夹即可,然后在文件夹…...
rocketmq服务的docker启动和配置
rocketmq的默认启动参数占用的内存实在是太大了,小于8G的电脑无法启动,docker中的开发环境又不可能用这么大,通用的该法是改sh文件 修改文件如下 runbroker.sh 默认8G JAVA_OPT"${JAVA_OPT} -server -Xms${Xms} -Xmx${Xmx} -Xmn${Xmn…...
BLE和经典蓝牙相比,有什么优缺点
蓝牙低功耗(Bluetooth Low Energy,简称 BLE)和经典蓝牙(Bluetooth Classic,即 BR/EDR,Basic Rate/Enhanced Data Rate)是蓝牙技术的两种主要模式。两者都有各自的优缺点,具体如下&am…...
ECharts图表图例知识点小结
ECharts 图表图例简述 一、知识点 1. 作用: - 用于标识图表中的不同系列,帮助用户理解图表所展示的数据内容。 2. 位置: - 可以通过配置项设置图例的位置,如 top 、 bottom 、 left 、 right 等。 3. 显示状态控制:…...
LabVIEW非接触式模态参数识别系统开发
基于LabVIEW的模态参数识别系统采用非接触式声学方法,结合LabVIEW软件和高精度硬件,实现机械结构模态参数的快速准确识别。降低了模态分析技术门槛,提高测试效率和准确性。 项目背景与意义: 传统的模态分析方法,如锤击法&#x…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
