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…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础
在构建任何动态、数据驱动的Web API时,一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说,深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言,以及学会如何在Python中操作数据库,是…...