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…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
C++中vector类型的介绍和使用
文章目录 一、vector 类型的简介1.1 基本介绍1.2 常见用法示例1.3 常见成员函数简表 二、vector 数据的插入2.1 push_back() —— 在尾部插入一个元素2.2 emplace_back() —— 在尾部“就地”构造对象2.3 insert() —— 在任意位置插入一个或多个元素2.4 emplace() —— 在任意…...
数据可视化交互
目录 【实验目的】 【实验原理】 【实验环境】 【实验步骤】 一、安装 pyecharts 二、下载数据 三、实验任务 实验 1:AQI 横向对比条形图 代码说明: 运行结果: 实验 2:AQI 等级分布饼图 实验 3:多城市 AQI…...
