String s=new String(“abc”)创建了几个对象?

​   在探讨上述问题结论之前,我们需要了解常量池这个概念。

常量池

​   由于字符串在Java中被大量使用,为了避免每次都创建相同的字符串对象(这样就意味着占据更多内存),JVM对字符串对象做了一定的优化,有一块专门的区域来存储字符串常量,该区域就是字符串常量池。常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。

​   需要注意的是:

  • 在JDK1.6即以前,常量池位于JVM的方法区中。

  • 在JDK7即以后,常量池放在堆中。

    官网说明:

    Synopsis: In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.

  理解字符串常量池的概念后,我们来看一下代码:

public class StringDemo {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc"); System.out.println(str1==str2); //第七行
System.out.println(str2==str3);//第八行
}
}

​   你看到上述代码,预测一下控制台输出!

​   第7行输出true,第8行输出false。

执行过程:

  1. 执行String str1 = “abc”;时,JVM常量池中并没有"abc"这个字符串,此时会在常量池中创建这个对象,然后将引用赋给str1`。

  2. 执行String str2 = "abc";时,JVM在常量池中找到"abc"这个字符串了,所以直接将应用附给它。

  3. 执行String str3 = new String("abc");时,JVM会在堆中创建一个String对象,然后将传进去的常量池String对象中保存的char[]数组,赋给堆中的String。

    /**
    String类的部分源代码
    **/
    /** The value is used for character storage. */
    private final char value[]; /** Cache the hash code for the string */
    private int hash; // Default to 0 public String(String original) {//String的构造器
    this.value = original.value;
    this.hash = original.hash;
    }

回到最初的问题,String s=new String(“abc”)到底创建了几个对象?

​   如果在执行String s=new String(“abc”)这句话之前,常量池中并没有"abc",那么在创建new String()时会先在常量池中 创建字符串常量,然后通过这个字符串常量,在堆中创建一个新的字符串,但是这两个字符串对象(常量池中的"abc"和堆中的"abc")底层保存字符的数组都是一个

​   如果在执行之前就有了"abc"这个字符串常量了(例如上面的代码),在执行String s=new String(“abc”)这句话时,也就只在堆中创建一个对象了。

验证常量池中的"abc"和堆中的"abc"底层保存字符的数组都是一个

​  前面我们查看String的构造器后得出结论,采用new关键字在堆中创建的"abc"和常量池中"abc"虽然对象不是一个,但是它们两个对象底层指向的数组是一个,那我们就通过代码验证这个结论。

​   整体思路是这样的:我们通过反射,修改常量词中字符串对象底层数组的值,看堆中的String对象的值是否跟着改变:

@Test
public void test() throws Exception {
//在常量池中创建一个"abc"
String str = "abc";
//通过常量词中的"abc"在堆中创建一个String对象
String str2 = new String("abc"); //获取String类中的value字段
Field field = String.class.getDeclaredField("value");
//将字段设置为可访问的
field.setAccessible(true); //获取str对象上的value属性的值
char[] arr = (char[]) field.get(str);
arr[2]='1'; System.out.println(str);//输出:ab1
System.out.println(str2);//输出:ab1
}

你可能不知道的秘密——String s=new String(“abc”)到底创建了几个对象?的更多相关文章

  1. new String("ab")到底创建了几个对象说明

    new String("ab")到底创建了几个对象? 之前一直被这个问题困扰,网上一些描述的都不是很清楚,自己看了一些资料可算搞清楚了,那就在博客上记录一下吧! String st ...

  2. String,你到底创建了几个对象????

    String str=new String("aaa"); 这行代码究竟创建了几个String对象呢?答案是2个,而不是3个.由于 new String("aaa&quo ...

  3. String s="a"+"b"+"c"+"d";创建了几个对象?

    对于如下代码: package reviewTest; /** * @ClassName: StringTest * @Description: 测试String的字符串相加优化 * @author ...

  4. String,到底创建了多少个对象?

      String str=new String("aaa"); <span style="font-size:14px;">String str=n ...

  5. String s="a"+"b"+"c",到底创建了几个对象?

    首先看一下这道常见的面试题,下面代码中,会创建几个字符串对象? String s="a"+"b"+"c"; 如果你比较一下Java源代码和反 ...

  6. Java String Pool--String s = new String("a") 到底创建了几个对象?

    本篇重点(tips): 1. String Pool 是以Java 中 String 对象是不可变的这一特性为基础的 2. String Pool是Heap(堆)中的一块特殊空间(JDK 1.7 之前 ...

  7. POLARDB · 最佳实践 · POLARDB不得不知道的秘密(二)

    前言 POLARDB For MySQL(下文简称POLARDB)目前是阿里云数据库团队主推的关系型数据库.线上已经有很多企业用户在使用并且稳定运行了很久.当然,由于POLARDB是为云上环境专门打造 ...

  8. POLARDB · 最佳实践 · POLARDB不得不知道的秘密

    ## 前言 POLARDB作为阿里云下一代关系型云数据库,自去年9月份公测以来,收到了不少客户的重点关注,今年5月份商业化后,许多大客户开始陆续迁移业务到POLARDB上,但是由于POLARDB的很多 ...

  9. new String创建了几个对象

    String str = new String(“abc”)  到底创建了几个对象? 首先String str是定义了一个字符串变量,并未产生对象,=不产生对象,那么只有后面的new String(& ...

  10. 工作10年后,再看String s = new String("xyz") 创建了几个对象?

    这个问题相信每个学习java的同学都不陌生,作为一个经典的面试题,到现在工作这么多年了我真是认为挺操蛋的一个问题,在网上到现在你仍然可以看见很多讨论这个问题的人,其中不乏工作很多年的人都有争论,我认为 ...

随机推荐

  1. 双向链表的基本实现【数据结构与算法—TypeScript 实现】

    笔记整理自 coderwhy 『TypeScript 高阶数据结构与算法』课程 双向链表:拥有两个指针方向的链表 DoublyNode 结构: prev:指向上一个节点 value:节点值 next: ...

  2. HarmonyOS元服务开发实践:桌面卡片字典

     本文转载分享自华为开发者论坛<HarmonyOS元服务开发实践:桌面卡片字典>,作者:蛟龙腾飞   一.项目说明 1.DEMO创意为卡片字典. 2.不同卡片显示不同内容:微卡.小卡.中卡 ...

  3. 响应式系统与 React

    0x1 React 的历史与应用 应用场景 前端应用开发,如 Meta.Ins.Netflix 的网页版 移动原生应用开发,如 Ins.Discord 结合 Electron 进行桌面应用开发 发展历 ...

  4. Centos8安装docker-ce

    一.安装步骤 1.安装yum-utils yum install -y yum-utils 2.配置阿里源 yum-config-manager --add-repo http://mirrors.a ...

  5. 重新点亮shell————awk数组[十四]

    前言 简单介绍一下awk的数组. 正文 数组的定义: 数组的遍历: 删除数组: 例子: 例子2: 结 下一节awk函数.

  6. HL7消息结构

    HL7消息用于在不同的医疗保健系统之间传输电子数据,每个消息发送相关特定事件(例如患者入院)的信息.HL7消息采用人类可读格式,本节介绍HL7消息的内容以及HL7消息的组织方式. HL7消息由一个或多 ...

  7. 技术解读:现代化工具链在大规模 C++ 项目中的运用 | 龙蜥技术

    简介: 本文详细介绍我们在实际工作中的大型 C++ 项目中现代化工具链的实践以及结果. 编者按:C++ 语言与编译器一直都在持续演进,出现了许多令人振奋的新特性,同时还有许多新特性在孵化阶.除此之外, ...

  8. 从 VLAN 到 IPVLAN: 聊聊虚拟网络设备及其在云原生中的应用

    简介: 由于这篇文章真的很长,大量的篇幅在讲述内核的实现,如果你对这部分不感兴趣,那么在建议你在看完第一部分的三个问题后,思考一下,然后直接跳转到我们对问题的回答. 作者:张伟(谢石)   由于这篇文 ...

  9. Serverless 在阿里云函数计算中的实践

    简介: 近日,阿里云 aPaaS&Serverless 前端技术专家袁坤在 CSDN 云原生 meetup 长沙站分享了 Serverless 在阿里云函数计算 FC 的实践. 作者:CSDN ...

  10. 技术解读:英特尔 x86 平台上,AI 能力是如何进行演进的?(附PPT)

    ​简介:AI 生态系统是怎样的?其中又有哪些关键技术? AI 计算力的指数增长意味着,为了解决越来越复杂的用例,即使是 1000 倍的计算性能增长也很容易被消耗.因此,需要通过软件生态系统的助力,才能 ...