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. 活动开启 | 以梦筑码 · 不负韶华 开发者故事征集令,讲出你的故事,有机会参加HDC.Together 2023

      HarmonyOS面世以来,经历了3大版本迭代,系统能力逐步完善,生态加速繁荣.一路前行,是开发者们点亮漫天星光.点滴贡献,聚沙成塔,开发者们正用代码改变世界. 是梦想,激励我们一路前行.在黎明到 ...

  2. Tailwind CSS 使用指南

    0x01 概述 (1)简介 Tailwind CSS 官网:https://www.tailwindcss.cn/ Tailwind CSS 是一个 CSS 框架,使用初级"工具" ...

  3. 【7】SpringBoot是什么?SpringBoot的优缺点有哪些?

    随着动态语言的流行(Ruby.Groovy.Scala.Node.js),Java 的开发显得格外的笨重,繁多的配置.低下的开发效率.复杂的部署流程以及第三方技术集成难度大. 在上述环境下,Sprin ...

  4. apache 服务器配置常用知识点合集

    前言 因为当年周围同学都在学php,最为简单的就是学php 好就业啊,写个一些php,最后放弃了,apache也看了两眼吧.下面是我使用有记录的,没有记录的我后面会补上. 正文 域名配置 1.取消 N ...

  5. 从LLaMA-Factory项目认识微调

    概述 什么是LLaMA-Factory? LLaMA-Factory是一个在github上开源的,专为大模型训练设计的平台.项目提供中文说明,可以参考官方文档:https://github.com/h ...

  6. webpack中常见的Plugin?解决了什么问题?

    一.是什么 Plugin(Plug-in)是一种计算机应用程序,它和主应用程序互相交互,以提供特定的功能 是一种遵循一定规范的应用程序接口编写出来的程序,只能运行在程序规定的系统下,因为其需要调用原纯 ...

  7. 【笔记】Java相关大杂烩①

    [笔记]Java相关大杂烩 Java 程序的执行流程是? *.java 文件-->*.class 文件-->类装载器-->字节码校验器-->解释器-->操作系统平台 Ja ...

  8. 如何用一个插件解决 Serverless 灰度发布难题?

    简介: 我们可以发现相比使用控制台进行灰度发布,使用 FC-Canary 插件免去了用户手动创建版本.发布别名.关联触发器和管理自定义域名的麻烦,使用起来非常方便. 作者:长淇 导读 本文适合: 想了 ...

  9. 性能提升 57% ,SMC-R 透明加速 TCP 实战解析 | 龙蜥技术

    ​简介:SMC-R 是如何加速 TCP 应用? 编者按:TCP 协议作为当前使用最为广泛的网络协议,场景遍布移动通信.数据中心等.对于数据中心场景,通过弹性 RDMA 实现高性能网络协议 SMC-R, ...

  10. 「直播回顾」Mars应用与最佳实践

    简介: 本文首先对Mars的概念.功能.优势进行了介绍,随后,对Mars几个典型的应用场景进行介绍,并通过两个Demo展示了在使用Mars后数据科学性能的提升,最后总结了Mars的最佳实践,让使用Ma ...