别再问我 new 字符串创建了几个对象了!我来证明给你看!(上)

简介: 别再问我 new 字符串创建了几个对象了!我来证明给你看!

我想所有 Java 程序员都曾被这个 new String 的问题困扰过,这是一道高频的 Java 面试题,但可惜的是网上众说纷纭,竟然找不到标准的答案。有人说创建了 1 个对象,也有人说创建了 2 个对象,还有人说可能创建了 1 个或 2 个对象,但谁都没有拿出干掉对方的证据,这就让我们这帮吃瓜群众们陷入了两难之中,不知道到底该信谁得。


但是今天,老王就斗胆和大家聊聊这个话题,顺便再拿出点证据


以目前的情况来看,关于 new String("xxx") 创建对象个数的答案有 3 种:


  1. 有人说创建了 1 个对象;
  2. 有人说创建了 2 个对象;
  3. 有人说创建了 1 个或 2 个对象。


而出现多个答案的关键争议点在「字符串常量池」上,有的说 new 字符串的方式会在常量池创建一个字符串对象,有人说 new 字符串的时候并不会去字符串常量池创建对象,而是在调用 intern() 方法时,才会去字符串常量池检测并创建字符串。


那我们就先来说说这个「字符串常量池」。


字符串常量池


字符串的分配和其他的对象分配一样,需要耗费高昂的时间和空间为代价,如果需要大量频繁的创建字符串,会极大程度地影响程序的性能,因此 JVM 为了提高性能和减少内存开销引入了字符串常量池(Constant Pool Table)的概念。


字符串常量池相当于给字符串开辟一个常量池空间类似于缓存区,对于直接赋值的字符串(String s="xxx")来说,在每次创建字符串时优先使用已经存在字符串常量池的字符串,如果字符串常量池没有相关的字符串,会先在字符串常量池中创建该字符串,然后将引用地址返回变量,如下图所示:


image.png


以上说法可以通过如下代码进行证明:


public class StringExample {
    public static void main(String[] args) {
        String s1 = "Java";
        String s2 = "Java";
        System.out.println(s1 == s2);
    }
}


以上程序的执行结果为:true,说明变量 s1 和变量 s2 指向的是同一个地址。


在这里我们顺便说一下字符串常量池的再不同 JDK 版本的变化。


常量池的内存布局


JDK 1.7 之后把永生代换成的元空间,把字符串常量池从方法区移到了 Java 堆上


JDK 1.7 内存布局如下图所示:


image.png


JDK 1.8 内存布局如下图所示:


image.png


JDK 1.8 与 JDK 1.7 最大的区别是 JDK 1.8 将永久代取消,并设立了元空间。官方给的说明是由于永久代内存经常不够用或发生内存泄露,会爆出 java.lang.OutOfMemoryError: PermGen 的异常,所以把将永久区废弃而改用元空间了,改为了使用本地内存空间,官网解释详情:http://openjdk.java.net/jeps/122

相关文章
|
缓存
KVCache原理简述
KVCache原理简述
496 0
|
存储 小程序 前端开发
微信小程序进阶——后台交互个人中心授权登录
微信小程序进阶——后台交互个人中心授权登录
448 0
|
JSON 前端开发 Java
如何封装接口返回结构?
本文详细探讨了API接口返回结构统一化的必要性及其带来的优势,如降低开发的心智负担、减少前端开发难度和提高代码可维护性等。同时也分析了其潜在的缺点,例如灵活性降低和开发成本增加等问题。文章进一步讨论了在Spring Boot中实现统一接口返回结构的具体方法和技术细节,包括如何处理HTTP状态码、返回单个字符串的情况以及如何封装无返回值的接口等。此外,还介绍了如何利用Spring Boot的`ResponseBodyAdvice`和`@RestControllerAdvice`等特性来自动包装控制器方法的返回值及异常处理,以达到更加一致和标准化的接口响应结构。
279 3
如何封装接口返回结构?
|
10月前
|
测试技术 数据库 Python
Python装饰器实战:打造高效性能计时工具
在数据分析中,处理大规模数据时,分析代码性能至关重要。本文介绍如何使用Python装饰器实现性能计时工具,在不改变现有代码的基础上,方便快速地测试函数执行时间。该方法具有侵入性小、复用性强、灵活度高等优点,有助于快速发现性能瓶颈并优化代码。通过设置循环次数参数,可以更准确地评估函数的平均执行时间,提升开发效率。
270 61
Python装饰器实战:打造高效性能计时工具
|
机器学习/深度学习 人工智能 算法
探索深度学习在图像识别领域的最新进展
【10月更文挑战第10天】探索深度学习在图像识别领域的最新进展
353 0
|
机器人 C# 人工智能
智能升级:WPF与人工智能的跨界合作——手把手教你集成聊天机器人,打造互动新体验与个性化服务
【8月更文挑战第31天】聊天机器人已成为现代应用的重要组成部分,提供即时响应、个性化服务及全天候支持。随着AI技术的发展,聊天机器人的功能日益强大,不仅能进行简单问答,还能实现复杂对话管理和情感分析。本文通过具体案例分析,展示了如何在WPF应用中集成聊天机器人,并通过示例代码详细说明其实现过程。使用Microsoft的Bot Framework可以轻松创建并配置聊天机器人,增强应用互动性和用户体验。首先,需在Bot Framework门户中创建机器人项目并编写逻辑。然后,在WPF应用中添加聊天界面,实现与机器人的交互。
589 0
|
存储 安全 Java
|
关系型数据库 MySQL 数据库
实时计算 Flink版操作报错合集之在处理PostgreSQL数据库遇到报错。该如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
JavaScript Java 测试技术
基于springboot+vue.js的景区民宿预约系统附带文章和源代码设计说明文档ppt
基于springboot+vue.js的景区民宿预约系统附带文章和源代码设计说明文档ppt
184 0
|
JavaScript 前端开发 API
Vue 3 中的 Composition API 是什么?它的优势是什么?
Vue 3 中的 Composition API 是什么?它的优势是什么?