你可能不知道的秘密——String s=new String(“abc”)到底创建了几个对象?
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。
执行过程:
执行String str1 = “abc”;
时,JVM常量池中并没有"abc"这个字符串,此时会在常量池中创建这个对象,然后将引用赋给str1`。执行
String str2 = "abc";时,JVM在常量池中找到"abc"这个字符串了,所以直接将应用附给它。执行
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”)到底创建了几个对象?的更多相关文章
- new String("ab")到底创建了几个对象说明
new String("ab")到底创建了几个对象? 之前一直被这个问题困扰,网上一些描述的都不是很清楚,自己看了一些资料可算搞清楚了,那就在博客上记录一下吧! String st ...
- String,你到底创建了几个对象????
String str=new String("aaa"); 这行代码究竟创建了几个String对象呢?答案是2个,而不是3个.由于 new String("aaa&quo ...
- String s="a"+"b"+"c"+"d";创建了几个对象?
对于如下代码: package reviewTest; /** * @ClassName: StringTest * @Description: 测试String的字符串相加优化 * @author ...
- String,到底创建了多少个对象?
String str=new String("aaa"); <span style="font-size:14px;">String str=n ...
- String s="a"+"b"+"c",到底创建了几个对象?
首先看一下这道常见的面试题,下面代码中,会创建几个字符串对象? String s="a"+"b"+"c"; 如果你比较一下Java源代码和反 ...
- Java String Pool--String s = new String("a") 到底创建了几个对象?
本篇重点(tips): 1. String Pool 是以Java 中 String 对象是不可变的这一特性为基础的 2. String Pool是Heap(堆)中的一块特殊空间(JDK 1.7 之前 ...
- POLARDB · 最佳实践 · POLARDB不得不知道的秘密(二)
前言 POLARDB For MySQL(下文简称POLARDB)目前是阿里云数据库团队主推的关系型数据库.线上已经有很多企业用户在使用并且稳定运行了很久.当然,由于POLARDB是为云上环境专门打造 ...
- POLARDB · 最佳实践 · POLARDB不得不知道的秘密
## 前言 POLARDB作为阿里云下一代关系型云数据库,自去年9月份公测以来,收到了不少客户的重点关注,今年5月份商业化后,许多大客户开始陆续迁移业务到POLARDB上,但是由于POLARDB的很多 ...
- new String创建了几个对象
String str = new String(“abc”) 到底创建了几个对象? 首先String str是定义了一个字符串变量,并未产生对象,=不产生对象,那么只有后面的new String(& ...
- 工作10年后,再看String s = new String("xyz") 创建了几个对象?
这个问题相信每个学习java的同学都不陌生,作为一个经典的面试题,到现在工作这么多年了我真是认为挺操蛋的一个问题,在网上到现在你仍然可以看见很多讨论这个问题的人,其中不乏工作很多年的人都有争论,我认为 ...
随机推荐
- 如何保存/同步多架构容器 Docker 镜像
前言 随着容器.芯片技术的进一步发展,以及绿色.节能.信创等方面的要求,多 CPU 架构的场景越来越常见.典型的应用场景包括: 信创:x86 服务器 + 鲲鹏 ARM 等信创服务器: 个人电脑:苹果 ...
- 【鸿蒙千帆起】《钢岚》成为首款基于HarmonyOS NEXT开发的战棋新游
近日,紫龙游戏旗下BlackJack工作室全新战棋旗舰作品<钢岚>在华为游戏中心首发上线,并宣布<钢岚>完成鸿蒙原生应用开发,成为基于HarmonyOS NEXT开发的首款 ...
- Mysql之刷盘机制
一.刷盘机制总览 刷盘过程 mysql刷脏数据在写redo之后,逻辑跟oracle一致. checkpoint/commit -> 内存中的redo到redolog文件 -> 内存中的脏数 ...
- 重新点亮shell————测试命令[六]
前言 我们写好脚本之后希望有一个测试. 正文 介绍一下exit,如果exit 0,那么表示正常退出. 如果exit 10,也就是非0,那么就是异常退出. 然后这个test 标准为[]和 [[]]这样子 ...
- 重新整理 .net core 实践篇————防跨站脚本攻击[四十]
前言 简单整理一下跨站脚本攻击. 正文 攻击原理是这样子的: 这种攻击被攻击的面挺多的,比如说只要有一个可以让用户输入的注入脚本就都是一个问题. 给网站注入脚本 然后用户访问给网站注入的脚本 脚本里面 ...
- nuxt按需引入组件库(却加载所有图标问题),nuxt性能优化。
做一个官网,nuxt按需引入了antd_vue组件库,但是项目打包时,图标却又500K+,经过排查,发现icon和其他组件环环相扣的.如下:(我引入了这个翻页的组件,里面包含了两个翻页的图标) 但是它 ...
- KubeMeet|聊聊新锐开源项目与云原生新的价值聚焦点
简介: 10 月 16 日上海,OAM/KubeVela.OpenKruise.OCM 三大开源项目的社区负责人.核心贡献者和企业用户将齐聚 KubeMeet,和现场 100 名开发者聊聊新的技术环 ...
- [FE] WebStorm, ESLint: Trailing spaces not allowed
在 WebStorm 中搜索文件 .eslintrc.js 在里面的 rules 项中追加规则: 'no-trailing-spaces' : ['off', { 'skipBlankLines': ...
- [ELK] Elastic Stack 的安全性预览
注:ELK Stack 之后的版本都叫做 Elastic Stack,增加了 Beats 等组件. 安全性保护方式: 阻止未授权的访问,通过 密码认证保护.RBAC授权.IP 过滤. 保证数据完整性, ...
- 2018-11-19-win10-uwp-使用-Azure-DevOps-自动构建
title author date CreateTime categories win10 uwp 使用 Azure DevOps 自动构建 lindexi 2018-11-19 15:26:4 +0 ...