Java高效编程(6):避免创建不必要的对象

news2024/9/30 17:21:28

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界

在开发中,尽量复用已经存在的对象,而不是每次都创建一个功能等价的新对象。对象复用不仅速度更快,也显得更加优雅。尤其是对于不可变对象,可以始终安全地复用(详见【条目17】)。举一个极端的反例:

String s = new String("bikini"); // 不要这样做!

这种写法每次执行时都会创建一个新的 String 实例,而其实完全没有必要。字符串字面量 "bikini" 本身已经是一个 String 实例,它与构造函数生成的对象功能上完全相同。如果这种代码出现在循环或频繁调用的方法中,可能会无端创建成千上万的 String 对象,浪费资源。改进后的代码如下:

String s = "bikini";

此版本只使用了一个 String 实例,且在同一虚拟机中任何包含相同字面量的代码都会重用该对象,从而避免不必要的对象创建。

静态工厂方法的优势

在使用不可变类时,优先选择静态工厂方法(详见【条目1】),可以进一步避免创建不必要的对象。例如,Boolean.valueOf(String)Boolean(String) 构造函数更优,因为后者每次都会创建一个新对象,而前者可以选择复用已有的实例。实际上,Java 9 中已将 Boolean(String) 构造函数废弃。

除了不可变对象,某些可变对象在确保不会被修改的前提下也可以复用。对于某些开销较大的对象,反复创建显然是不划算的。这时我们可以通过缓存这些对象来实现复用,减少性能消耗。

避免重复创建昂贵对象

并不是所有对象的创建成本都是相同的。假设我们要编写一个方法,用于判断某个字符串是否是有效的罗马数字。最简单的实现方式是使用正则表达式:

// 性能可以显著提升!
static boolean isRomanNumeral(String s) {
    return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}

虽然这种写法简洁,但每次调用 matches 方法时,都会新建一个 Pattern 对象,并在使用后将其丢弃,导致性能下降。为了提升效率,可以将正则表达式编译为一个静态的 Pattern 对象并缓存起来:

// 通过复用昂贵对象提升性能
public class RomanNumerals {
    private static final Pattern ROMAN = Pattern.compile(
            "^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");

    static boolean isRomanNumeral(String s) {
        return ROMAN.matcher(s).matches();
    }
}

改进后的 isRomanNumeral 方法在高频调用时性能提升显著。在我的机器上,原版本处理8字符输入需要1.1微秒,而改进版本只需0.17微秒,速度提升了6.5倍。此外,代码的可读性也有所提高,因为我们将正则表达式封装成了具有语义的静态字段 ROMAN,使代码更加清晰。

复用其他类型的对象

不仅仅是不可变对象可以复用,有时一些"适配器"(如视图)对象也可以复用。适配器对象是一种将操作委托给其他对象的模式,通常只提供不同的接口,而不包含额外的状态。例如,Map 接口的 keySet 方法返回一个视图对象,表示 Map 中的所有键。尽管 keySet 返回的实例是可变的,但其背后依赖的是同一个 Map 实例,因此无论 keySet 被调用多少次,返回的对象功能上都是相同的。

// 返回相同的 Set 视图对象
Set<String> keys1 = myMap.keySet();
Set<String> keys2 = myMap.keySet();
// keys1 和 keys2 实际上是同一个视图对象

在这种情况下,重复创建视图对象不仅没有任何好处,还会徒增对象数量,增加内存开销。

自动装箱的代价

自动装箱(autoboxing)是另一种常见的导致不必要对象创建的机制。自动装箱允许我们在基本类型和包装类型之间自由切换,编译器会自动进行类型转换。然而,自动装箱带来了性能上的隐性成本。例如,下面的代码在计算所有正整数的和时,由于一个细微的错误而导致大量不必要的对象创建:

// 极其缓慢!能发现对象创建的原因吗?
private static long sum() {
    Long sum = 0L; // 使用了包装类型 Long,而不是基本类型 long
    for (long i = 0; i <= Integer.MAX_VALUE; i++)
        sum += i;
    return sum;
}

上述代码每次 long 加法操作都会创建一个新的 Long 实例,导致生成约 2^31 个不必要的对象,极大地影响了性能。将 Long 换为 long 后,运行时间从 6.3 秒减少到 0.59 秒,性能提升了十倍。

对象创建并不总是昂贵

需要注意的是,本文讨论的并不是说对象创建本身是昂贵的。实际上,现代 JVM 对象创建和垃圾回收的效率非常高,创建一些轻量级对象并不会带来显著的性能开销。因此,为了提升代码的简洁性或可读性,适当地创建对象是值得的。反过来,手动管理对象池通常是一个糟糕的主意,除非对象非常重量级(例如数据库连接)。维护对象池会导致代码复杂度增加,内存占用上升,性能反而下降。

总结

不要为了性能避免创建对象,而是要避免不必要的对象创建。在可以复用对象时,应优先复用,尤其是不可变对象、昂贵的对象和适配器对象等。使用自动装箱时也应小心,避免无意中引入不必要的对象创建。同时,不要误认为对象创建一定是昂贵的——现代 JVM 的垃圾回收机制已经非常高效。只有在对象真正影响性能时,才需要关注对象的创建和复用。

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

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

相关文章

学习threejs,添加户外光照光源

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言二、&#x1f340;绘制任意字体模型…

windows 桌面采集音频

头文件&#xff1a; #ifndef __CAPTURE_AUDIO__ #define __CAPTURE_AUDIO__#include <functional> #include <windows.h> #pragma comment(lib, "winmm.lib")class CaptureAudio { public:CaptureAudio();~CaptureAudio();public:bool Init(const std::…

云计算Openstack Glance

OpenStack Glance&#xff08;或称为Glance&#xff0c;但通常OpenStack官方文档中使用的是“Glance”作为项目代号&#xff09;是OpenStack的镜像服务组件&#xff0c;为创建虚拟机提供镜像服务。以下是对OpenStack Glance的详细解析&#xff1a; 一、基本功能 Glance主要提…

【HTML并不简单】笔记2-你不知道的a元素属性:target、download、ping、referrerpolicy和href

文章目录 target属性download属性ping属性referrerpolicyhref细节自动绝对地址锚点定位无障碍访问为何base元素无人问津实现链接元素a的嵌套 《HTML并不简单&#xff1a;Web前端开发精进秘籍》张鑫旭 笔记 target属性 有场景如下&#xff1a; 在线写作工具经常会有预览功能&a…

源2.0-M32大模型适配AutoGPTQ工具及量化推理教程

AutoGTPQ简介 AutoGPTQ‌是一个开源工具包&#xff0c;专注于简化大规模语言模型(LLMs)的量化过程。它基于高效的GPTQ算法开发&#xff0c;主要使用Python编程语言&#xff0c;并依托PyTorch框架来实现量化功能。AutoGPTQ的设计目标是为开发者和研究人员提供一个易于使用的API接…

【Golang】关于Go语言数学计算、随机数生成模块--math

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

多功能声学气膜馆:承载梦想与希望的舞台—轻空间

在9月29日上午&#xff0c;苏州大学应用技术学院的2024级新生开学典礼暨开学第一课在轻空间建造的多功能声学气膜馆内盛大举行。这一盛典不仅见证了2849名新生的入学&#xff0c;也展示了气膜馆的独特魅力与优越功能。 卓越的声学表现 声学气膜馆采用高性能材料&#xff0c;确保…

Linux-基础实操篇-组管理和权限管理(上)

Linux 组基本介绍 在 linux 中的每个用户必须属于一个组&#xff0c;不能独立于组外。在 linux 中每个文件 有所有者、所在组、其它组的概念。 用户和组的基本概念&#xff1a; 用户名&#xff1a;用来识别用户的名称&#xff0c;可以是字母、数字组成的字符串&#xff0…

解决DHCP服务异常导致设备无法获取IP地址的方法

DHCP在网络环境中会自动为网络中的设备分配IP地址和其他关键网络参数&#xff0c;可以简化网络配置过程。但是&#xff0c;如果DHCP服务出现异常时&#xff0c;设备可能无法正常获取IP地址&#xff0c;会影响到网络通信。 本文讲述一些办法可以有效解决DHCP服务异常导致设备无法…

YAML管理接口框架配置的最佳实践!!

YAML 文件在接口框架中作为配置管理的语言&#xff0c;以其简洁、直观的语法&#xff0c;迅速成为开发者的宠儿。然而&#xff0c;如何高效地管理和组织接口框架的配置&#xff0c;往往是一个容易被忽视的难题。你是否曾因为冗长的配置文件而感到头疼&#xff1f;今天&#xff…

干冰清洗机的工作原理

干冰清洗机的工作原理主要基于干冰的物理特性&#xff0c;特别是其升华过程。以下是干冰清洗机工作原理的详细解释&#xff1a; 一、干冰的制备 制冰系统&#xff1a;干冰清洗机内部配备有制冰系统&#xff0c;该系统将液态二氧化碳&#xff08;CO₂&#xff09;快速冷却并压…

HTTP协议讲解,请求报文与响应报文都是什么?网络控制台查看HTTP请求

目录 一. HTTP解析 二. 请求报文 2.1 请求行 2.1.1 请求类型 2.1.2 请求URL路径 2.1.3 发送的HTTP请求的版本 2.2 请求头 2.2.1 Host&#xff1a;主要用来实现虚拟主机技术 2.2.2 Cookie&#xff1a;一种让浏览器帮忙携带信息的手段 2.2.3 Content—type&#xff1a;…

揭秘分布式定时任务在人工智能RPA机器人中的应用|实在RPA研究

一、引言 在人工智能技术不断突破的今天&#xff0c;RPA智能机器人已经渗透到各行各业&#xff0c;成为企 业提升效率、降低成本的重要工具。而在机器人高效运作的背后&#xff0c;分布式定时任务发挥着 不可替代的作用。本文将深入探讨分布式定时任务在人工智能机器人中的应用…

leetcode-链表篇3

leetcode-61 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3]示例 2&#xff1a; 输入&#xff1a;head [0,1,2], k 4 输出&#x…

opencv - Fourier Transform 傅里叶变换

目标 在本节中&#xff0c;我们将学习 使用 OpenCV 查找图像的傅里叶变换利用 Numpy 中可用的 FFT 函数傅里叶变换的一些应用我们将看到以下函数&#xff1a;cv.dft()、cv.idft() 等 理论 傅里叶变换用于分析各种滤波器的频率特性。对于图像&#xff0c;2D 离散傅里叶变换 …

优选驾考系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;驾校管理&#xff0c;驾考文章管理&#xff0c;驾照类型管理&#xff0c;报名入口管理&#xff0c;学员报名管理&#xff0c;练车预约管理&#xff0c;考试场地管理 微信端账号功能包括&#xff1a;系…

【羊毛资源】华为云开发者云主机免费申请使用指南

本文内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01; 如果对您有帮助&#xff0c;烦请点赞、关注、转发、订阅专栏&#xff01; 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】&#xff08;全…

【GAN 图像生成】

理论知识学习&#xff1a; PART 1&#xff1a; 生成对抗网络GAN 深度学习模型&#xff0c;用于生成数据 对抗式训练&#xff0c;生成器v判别器 DCGAN>WGAN>StyleGAN技术不断进化 GAN在艺术创作。数据增强领域应用越来越广泛 应用&#xff1a; GAN在图像合成&#x…

生信初学者教程(十二):数据汇总

文章目录 介绍加载R包导入数据汇总表格输出结果总结介绍 在本教程中,汇总了三个肝细胞癌(HCC)的转录组数据集,分别是LIRI-JP,LIHC-US/TCGA-LIHC和GSE14520,以及一个HCC的单细胞数据集GSE149614的临床表型信息。这些数据集为科研人员提供了丰富的基因表达数据和相关的临床…

SqlAlchemy使用教程(七) 异步访问数据库

SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门SqlAlchemy使用教程(六) – O…