String s=new String(“hello”)的执行过程
一. 介绍
String 是Java.long包下的String类,是一个特殊的引用类型,用于表示字符串。它提供了许多方法来操作和处理字符串,比如连接、截取、查找、替换等。String类内部使用字符数组( char[] ) 来存储字符串的内容,value字段被final修饰,String对象一旦创建后,其值就不可改变。String对象的值存储在常量池中,每次修改操作都会创建一个新的字符串对象,并且如果常量池中已经存在相同内容的字符串,就会直接引用该字符串而不创建新对象。
String 常见的两种赋值方式:
1. 直接赋值:通过使用双引号将字符串文字包围起来进行赋值,例如:String str = "Hello World!";
2. 构造函数:通过调用String类的构造函数来创建字符串对象并进行赋值,例如:String str = new String("Hello World!");
二. 执行过程
在了解执行过程前,先明白常量池的作用,String为什么要引用常量池?
String类引用常量池的目的是提高内存利用率和性能。常量池是Java虚拟机中用于存储字符串常量的一块区域,它位于堆区之外,属于方法区的一部分。
当我们使用双引号创建一个字符串对象时,如果常量池中已经存在相同内容的字符串,则不会再创建新的对象,而是直接引用已存在的字符串对象。这样可以节约内存空间,避免不必要的对象创建。
另外,String类的一些常用方法如equals()和hashCode()等都依赖于常量池的引用,如果不使用常量池,那么每次字符串比较和哈希计算都需要逐个字符比较,效率较低。而通过引用常量池,可以利用字符串对象的唯一性快速进行比较和哈希计算,提高了程序的执行效率。
总而言之,引用常量池可以有效地节省内存开销,并提升字符串操作的性能。
1. 直接赋值的执行过程:
- 编译阶段,当遇到一个字符串直接赋值的语句,例如:String str = "Hello"; 编译器会查询该字符在常量池("Hello")在常量池中是否存在;
如果常量池中不存在相同的字符串"Hello",则会在常量池创建新的字符串对象;
如果常量池中存在相同字符串"Hello",则直接返回该字符串的引用;
- 运行阶段,变量 String str 会在栈内存中占用空间,JVM会将字符串常量的引用指向变量str。这样,变量str就引用了常量池中的字符串对象。
2. 构造函数的执行过程:
- 编译阶段:如果传入的参数是字符串常量,例如:String str = new String("hello"); 编译器会在编译期间将其作为字符串常量处理,并在常量池中创建一个对应的字符串对象。如果已经存在相同内容的字符串常量,则不会重复创建,而是共享已存在的对象。
- 运行阶段:String str = new String() 左进栈 ,右进堆;先进栈,后进堆;
在栈内存上分配空间,创建一个名为str的引用变量,用来存储引用地址;
在堆内存中创建一个新的String对象,并引用常量池中的字符串地址。
三. 区别
1. 内存分配
String str = "hello" 的方式 JVM 会将其分配到常量池中,此时仅产生一个字符串对象的内存空间。
String str = new String("hello”),会在堆内存中new一个对象,若常量池中没有该引用,则会在创建在常量池中创建新的字符串,因此使用new String() 会比直接赋值占用内存多。
2. 灵活度
String str = "hello" ,仅支持字符串之间的引用了;
String str = new String("hello”) ,构造方法提供了更灵活的方式来创建字符串对象,并且可以通过转换类型的功能满足不同的需求。需要注意的是,这些构造方法创建的字符串对象是不可变的,即不能修改其内容。
四. 扩展
String中的构造方法,支持哪种类型转换

构造方法使用方式:
public static void main(String[] args) throws UnsupportedEncodingException {
byte[] bytes = {99, 100, 101, 102};
// public String(byte bytes[])
// 通过使用平台的默认字符集解码指定的字节数组来构造新的 String 。
String str1 = new String(bytes);
System.out.println(str1);
// public String(byte bytes[], Charset charset)
// 指定字符集,构建一个新的String字符串
// bytes[]:字节数组,包含要构建字符串的字符。
// charset: charset参数指定要使用的字符集
Charset charset = Charset.forName("UTF-8");
String str2 = new String(bytes, charset);
System.out.println(str2);
// public String(byte bytes[], int offset, int length)
// 将字节数组中的一部分截取出来变成一个字符串 offset指的是偏移量或者索引
// bytes:要转换的字节数组。
// offset:开始转换的位置,即字节数组的起始索引。
// length:要转换的字节长度,即要转换的字节数。
String str3 = new String(bytes, 1, 2);
System.out.println(str3);
// public String(byte bytes[], String charsetName)
// 构造一个新的String由指定用指定的字节的数组解码charset 。
// byte数组(bytes[]):表示要用于构造字符串的字节数组。
// 字符集名称(String charsetName):表示将字节数组转换为字符串时,字符集的String类型的名字。
String str4 = new String(bytes, "utf-8"); //解码需要抛异常
System.out.println(str4);
// public String(char value[])
// 使用字符数组构建新的字符串
char[] chars = {'a', 'b', 'c', 'd', 'e'};
String str5 = new String(chars);
System.out.println(str5);
// public String(char value[], int offset, int count)
// 构造方法通过将字符数组的一部分转换为字符串来创建新的字符串对象。
// value:字符数组,包含要构建字符串的字符。
// offset:整数,指定字符数组中要开始构建字符串的起始位置的偏移量。
// count:整数,指定从起始位置开始构建字符串的字符数量。
String str6 = new String(chars, 2, 3);
System.out.println(str6);
// public String(int[] codePoints, int offset, int count)
// 传入int作为参数,构建新的String字符串,这个int是这个字对应的Unicode(16进制数)
// codePoints:一个包含 Unicode 码点的整数数组。
// offset:指定从 codePoints 数组的哪个位置开始获取码点。
// count:指定要使用的码点数量。
// 该方法会根据提供的码点数组,从指定位置开始取出指定数量的码点,并将它们组合成一个字符串。
// 需要注意的是,每个码点都代表一个字符,而不是字节。在 Java 中,Unicode 字符以码点的形式表示,其中一些字符可能由多个码元(code unit)组成。
int[] codePoints = {104, 101, 108, 108, 111};
String str7 = new String(codePoints, 1, 4); // 在代码示例中使用的码点是整数值,可以直接使用对应字符的 ASCII 码来表示。
System.out.println(str7);
// public String(String original)
// 常使用的方法
// original:要复制到新String对象中的字符串。
String str8 = new String("Hello");
System.out.println(str8);
// public String(StringBuffer buffer)
// 将StringBuffer转换为String,并且在需要不可变字符串的场景中更加适用。
StringBuffer sbf = new StringBuffer("Hello");
String str9 = new String(sbf);
System.out.println(str9);
// public String(StringBuilder builder)
StringBuilder sb = new StringBuilder("Hello");
String str10 = new String(sb);
System.out.println(str10);
}
输出结果:
cdef
de
cdef
abcde
cde
ello
Hello
Hello
Hello
完!
String s=new String(“hello”)的执行过程的更多相关文章
- ASP.NET Web API 过滤器创建、执行过程(二)
ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...
- ASP.NET Web API 过滤器创建、执行过程(一)
ASP.NET Web API 过滤器创建.执行过程(一) 前言 在上一篇中我们讲到控制器的执行过程系列,这个系列要搁置一段时间了,因为在控制器执行的过程中包含的信息都是要单独的用一个系列来描述的,就 ...
- ASP.NET Web API 控制器执行过程(一)
ASP.NET Web API 控制器执行过程(一) 前言 前面两篇讲解了控制器的创建过程,只是从框架源码的角度去简单的了解,在控制器创建过后所执行的过程也是尤为重要的,本篇就来简单的说明一下控制器在 ...
- 通过源码了解ASP.NET MVC 几种Filter的执行过程
一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神的工作,而且很多人觉得平时根本不需要知道这些,会用就行了.其实阅读源 ...
- Hadoop MapReduce执行过程详解(带hadoop例子)
https://my.oschina.net/itblog/blog/275294 摘要: 本文通过一个例子,详细介绍Hadoop 的 MapReduce过程. 分析MapReduce执行过程 Map ...
- Web APi之过滤器执行过程原理解析【二】(十一)
前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...
- JVM-绘图展现字节码执行引擎执行过程
在我的上一篇博客JVM-String比较-字节码分析中介绍了String字符串比较的原因,借着分析字节码的机会,我这篇博客将会绘图展现方法内部字节码执行过程. 话不多说,贴上我们将要分析的Java方法 ...
- 绝对干货:自定义msi安装包的执行过程
有时候我们需要在程序中执行另一个程序的安装,这就需要我们去自定义msi安装包的执行过程. 比如我要做一个安装管理程序,可以根据用户的选择安装不同的子产品.当用户选择了三个产品时,如果分别显示这三个产品 ...
- saiku执行过程代码跟踪
使用了很久的saiku,决定跟踪一下代码,看看它的执行核心过程: 一.入口controller代码 1.1.页面打开之后,会发送一个ajax请求 Request URL: http://l-tdata ...
- 四、Struts2的执行过程和原理
执行过程和原理(可能面试题) 学习目标:熟知struts2的执行过程(下图记住).源码可以不看 a.过滤器的初始化 .StrutsPrepareAndExecuteFilter是一个过滤器,过滤器就有 ...
随机推荐
- 最新版本 Stable Diffusion 开源 AI 绘画工具之中文自动提词篇
目录 标签生成器 提示词自动补全 标签生成器 由于输入正向提示词 prompt 和反向提示词 negative prompt 都是使用英文,所以对学习母语的我们非常不友好 使用网址:https://t ...
- Email发送邮件使用ical4j将时间同步日历中
1.Maven依赖 <!--邮件--> <dependency> <groupId>org.springframework.boot</groupId> ...
- Vue实战案例
Vue项目案例 结合之前学习的 vue.js.脚手架.vuex.vue-router.axios.elementui 等知识点,来开发前端项目案例(仅前端不含后端). 1.项目搭建 其实就是将我们项目 ...
- MySQL高频面试题
什么是MySQL MySQL是一个关系型数据库,它采用表的形式来存储数据.你可以理解成是Excel表格,既然是表的形式存储数据,就有表结构(行和列).行代表每一行数据,列代表该行中的每个值.列上的值是 ...
- Linux 升级sudo到 1.9.12p1,解决漏洞CVE-2022-43995
一.查看sudo版本 sudo -V 二.下载最新版本到服务器并解压 wget https://www.sudo.ws/dist/sudo-1.9.12p1.tar.gz && tar ...
- 🚀 jdbc-plus是一款基于JdbcTemplate增强工具包, 已实现分页、多租户、动态表名等插件,可与mybatis、mybatis-plus等混合使用
jdbc-plus简介 jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页.多租户.动态表名等插件,可自定义扩展插件,可与mybatis.myba ...
- 2023-02-15:商场中有一展柜A,其大小固定,现已被不同的商品摆满, 商家提供了一些新商品B,需要对A中的部分商品进行更新替换, B中的商品可以自由使用,也就是可以用B中的任何商品替换A中的任何
2023-02-15:商场中有一展柜A,其大小固定,现已被不同的商品摆满, 商家提供了一些新商品B,需要对A中的部分商品进行更新替换, B中的商品可以自由使用,也就是可以用B中的任何商品替换A中的任何 ...
- 2021-07-09:股票问题6。给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付
2021-07-09:股票问题6.给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :整数 fee 代表了交易股票的手续费用.你可以无限次地完成交易,但是你每笔交易都需要付 ...
- 2021-11-15:四数相加 II。给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:0 <= i,
2021-11-15:四数相加 II.给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:0 <= ...
- Redis - 二进制位数组
简介 Redis 使用字符串对象来表示位数组,因为字符串对象使用的 SDS 数据结构是二进制安全的,所以程序可以直接使用 SDS 结构来保存位数组,并使用 SDS 结构的操作函数来处理位数组. 在 S ...