【Java】String类

news2025/1/12 15:47:44

1. String内部声明

jdk8以前:
private final char value[];

  • final:指明数组一旦初始化,其地址就不能改变

jdk9以后:
private final byte[] value;,为节省内存空间而优化

  • final:指明数组一旦初始化,其地址就不能改变
  • 将char换成byte是为了节省空间,因为国外代码都是拉丁系列(英文)的文字,1byte保存一个character
  • 但是使用的是utf-16(中文)的话,使用2byte保存1character

2. String的不可变性

不管什么操作改变的永远是引用地址,不是字符串!

“=”声明的字符串保存在字符串常量池中,new String()创建的字符串保存在堆中

"="声明的字符串变量,底层怎么操作的?

保存在字符串常量池中共。

重新赋值时:

  • 不是覆盖原来的值,而是在常量池中给新字符开辟一个新的空间保存,并将这个空间地址指向这个引用。原来的字符常量依然存在,便于复用。
  • 当别的引用被赋予这个原来的值时,将这个值的地址指向他即可,不会重新开辟空间。
    在这里插入图片描述

字符串拼接时:

  • 不是对原来字符串进行修改,而是 return new String(...)创建了一个新的String对象。
  • 不是保存在常量池中,因为是对象所以保存在堆中。
  • 为了方便理解,这里对字符串保存方式做了简化,具体的下后边的 “通过new创建对象时:”
    在这里插入图片描述

字符replace()替换操作:

  • 不是对原来字符串进行修改,而是 return new String(...)创建了一个新的String对象。
  • 不是保存在常量池中,因为是对象所以保存在堆中。
    • 为了方便理解,这里对字符串保存方式做了简化,具体的下后边的 “通过new创建对象时:”在这里插入图片描述

new String()的方式创建的字符串,底层怎么操作?

保存在堆空间中,因为是对象。

通过new创建对象时:

虽然我们只new了一个对象,但底层是创建了两个对象。

  • 一个对象是我们new的对象在堆中,用于保存字符串地址
  • 另一个对象是字符串常量池的byte[]/char[]对象,用于保存字符串地址
  • 字符串被单独放到了一块空间,并没有保存到某一个对象中,方便复用。

字符串还是保存在字符串常量池的,两个对象都通过value属性指向了字符串常量的位置。

注意: 内存中两个对象保存的相同字符串的地址是相同的,但是两个对象对应的引用地址是不行同的。

在这里插入图片描述

3. 字符串+拼接操作

由图可见,有变量参与的和字符串常量的拼接,底层的操作是不同的(比较值不一样)。

  • 情况1:常量 + 常量:结果仍在常量池中(注:可能使字面量常量,也可能是final修饰的常量)
  • 情况2:常量 + 变量 或 变量 + 变量:都会new一个新的字符串,保存在堆空间,返回堆空间地址
  • 情况3:调用字符串的intern():返回的是字符串常量池中字面量的地址。
    在这里插入图片描述

字面量字符串

对于字面量字符串,Java编译后会自动将其拼接。对于有变量参与的则不同。

所以对于字面量声明的字符串,不会创建对象,比较的是值,所以为true。
在这里插入图片描述

有变量参与的

有变量参与的,底层会通过new重新创建对象,所以引用保存了不同的内存地址。

所以 “==”比较的是内存地址,输出false。

底层通过StringBuilder.append()方法向StringBuilder添加元素,最后通过StringBuilder.toString()方法将StringBuilder转换成String(new String())。
在这里插入图片描述

intern()方法返回字符串常量池的地址

因为返回 的是地址,所以“==”结果为true
在这里插入图片描述

4. 字符串常量池

注意:字符串是引用数据类型,引用保存的是内存地址

  • 我们声明的字符串常量都保存在字符串常量池中,
  • 声明相同的字符串不会重复创建,而是给予相同的指针
  • jdk7之前常量池在方法区中,jdk7之后将其放到了堆空间
    • 因为堆空间被GC垃圾回收比较频繁,便于及时清理不使用的字符串常量,节省内存空间。

5. String常用API

1. 构造器

  • public String() :初始化新创建的 String对象,以使其表示空字符序列。
  • String(String original): 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
  • public String(char[] value) :通过当前参数中的字符数组来构造新的String。
  • public String(char[] value,int offset, int count) :通过字符数组的一部分来构造新的String。
  • public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String。
  • public String(byte[] bytes,String charsetName) :通过使用指定的字符集解码当前参数中的字节数组来构造新的String。

示例:

//字面量定义方式:字符串常量对象
String str = "hello";

//构造器定义方式:无参构造
String str1 = new String();

//构造器定义方式:创建"hello"字符串常量的副本
String str2 = new String("hello");

//构造器定义方式:通过字符数组构造
char chars[] = {'a', 'b', 'c','d','e'};     
String str3 = new String(chars);
String str4 = new String(chars,0,3);

//构造器定义方式:通过字节数组构造
byte bytes[] = {97, 98, 99 };     
String str5 = new String(bytes);
String str6 = new String(bytes,"GBK");

2. String与其他结构间的转换

字符串 --> 基本数据类型、包装类:

  • Integer包装类的public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
  • 类似地,使用java.lang包中的Byte、Short、Long、Float、Double类调相应的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型。

基本数据类型、包装类 --> 字符串:

  • 调用String类的public String valueOf(int n)可将int型转换为字符串
  • 相应的valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double d)、valueOf(boolean b)可由参数的相应类型到字符串的转换。

字符数组 --> 字符串:

  • String 类的构造器:String(char[]) 和 String(char[],int offset,int length) 分别用字符数组中的全部字符和部分字符创建字符串对象。

字符串 --> 字符数组:

  • public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。
  • public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法。

字符串 --> 字节数组:(编码)

  • public byte[] getBytes() :使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
  • public byte[] getBytes(String charsetName) :使用指定的字符集将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。

字节数组 --> 字符串:(解码)

  • String(byte[]):通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
  • String(byte[],int offset,int length) :用指定的字节数组的一部分,即从数组起始位置offset开始取length个字节构造一个字符串对象。
  • String(byte[], String charsetName ) 或 new String(byte[], int, int,String charsetName ):解码,按照指定的编码方式进行解码。

3. 常用方法

常用方法

(1)boolean isEmpty():字符串是否为空
(2)int length():返回字符串的长度
(3)String concat(xx):拼接
(4)boolean equals(Object obj):比较字符串是否相等,区分大小写
(5)boolean equalsIgnoreCase(Object obj):比较字符串是否相等,不区分大小写
(6)int compareTo(String other):比较字符串大小,区分大小写,按照Unicode编码值比较大小
(7)int compareToIgnoreCase(String other):比较字符串大小,不区分大小写
(8)String toLowerCase():将字符串中大写字母转为小写
(9)String toUpperCase():将字符串中小写字母转为大写
(10)String trim():去掉字符串前后空白符
(11)public String intern():结果在常量池中共享

4. 查找

(13)boolean contains(xx):是否包含xx
(13)int indexOf(xx):从前往后找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1
(14)int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
(15)int lastIndexOf(xx):从后往前找当前字符串中xx,即如果有返回最后一次出现的下标,要是没有返回-1
(16)int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。

5. 查找

(17)boolean contains(xx):是否包含xx
(18)int indexOf(xx):从前往后找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1
(19)int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
(20)int lastIndexOf(xx):从后往前找当前字符串中xx,即如果有返回最后一次出现的下标,要是没有返回-1
(21)int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。

6. 和字符/字符数组相关

(22)char charAt(index):返回[index]位置的字符
(23)char[] toCharArray(): 将此字符串转换为一个新的字符数组返回
(24)static String valueOf(char[] data) :返回指定数组中表示该字符序列的 String
(25)static String valueOf(char[] data, int offset, int count) : 返回指定数组中表示该字符序列的 String
(26)static String copyValueOf(char[] data): 返回指定数组中表示该字符序列的 String
(27)static String copyValueOf(char[] data, int offset, int count):返回指定数组中表示该字符序列的 String

7. 开头与结尾

(28)boolean startsWith(xx):测试此字符串是否以指定的前缀开始
(29)boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
(30)boolean endsWith(xx):测试此字符串是否以指定的后缀结束

8. 替换

(31)String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 不支持正则。
(32)String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
(33)String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
(34)String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/379655.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

这些让人变笨的食物你是不是天天吃?

我们关注食物的营养,关注它对身材、健康的影响。现在,我们发现有些食物,还会影响人的神经系统、认知能力。简而言之,就是有些食物可能会让人变笨。《美国医学会神经病学杂志》上的一项研究,分析了超加工食物与认知能力…

【蓝桥杯入门到入土】最基础的数组你真的掌握了吗?

文章目录一:数组理论基础二:数组知识点总结三:数组这种数据结构的优点和缺点是什么?四:实战解题1. 移除元素暴力解法双指针法2.有序数组的平方暴力解法双指针法最后说一句一:数组理论基础 首先要知道数组在…

【数据结构】堆的详解

本章的知识需要有树等相关的概念,如果你还不了解请先看这篇文章:初识二叉树 堆的详解一、二叉树的顺序结构及实现1、二叉树的顺序结构2、堆的概念及结构二、堆的简单实现 (以大堆为例)1、堆的定义2、堆的初始化3、堆的销毁4、堆的打印5、堆的插入6、堆顶元素的获取7…

网络传输:linux下的网络请求和下载(ping wget curl)、端口

一、下载和网络请求 1.ping命令 可以通过ping命令,检查指定的网络服务器是否可连通状态 语法:ping [-c num] ip或主机名 选项: -c 检查的次数,若不使用-c,将无限次数持续检查参数:ip或主机名&#xff0c…

基于Python的时间序列异常值检测

今天我们介绍一下使用python做时间序列数据分析和预测中异常值检测的方法,常用的异常值检测方法有以下几种: 3sigma: 基于正太分布,当数据值超过3个标准差(3sigma)时为异常值。z-score : z标准分数,它测量数据值到平均值的距离,当…

pandas对某一列的种类编码

文章目录背景实现背景 如果某一列的种类特别多,想要通过映射来编码,这样非常麻烦,所以可以对一个列全部一次性进行编码。 例如我的数据如下: 我需要编码专业这个列,我们可以看到这一列很多: 实现 使用…

【Unity】P3 基础设定

Unity基础设定父子关系InspectorTransformMesh FilterMesh Rendener第二种常用的父子操作Global 与 Local 模式Pivot 与 Center 模式声音组件创建多场景Asset 资源商店前言 上一篇博文主要围绕Unity的静态基础操作部分,从创建好的一个小方块cube开始,到对…

Selenium基于POM的自动化测试实践

什么是Page Object模式 Page Object 见名知意,就是页面对象,并将页面元素定位方法和元素操作进行分离。在实际自动化测试实战过程中,我们一般对脚本的实现分为三层: (1)对象层: 用于存放页面元素定位和控件操作 (2)逻…

《Nacos(3) - 集群搭建(详细)》

《Nacos(3) - 集群搭建》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《Nacos3 - 集群搭建》《Nacos(3) - 集群搭建》1.集群结构图2.搭建集群2.1.初始化数据库2.2.下载nacos2.3.配置Nacos2.4.启动2.5.nginx反向代理2.6.优化1.集群结构图 官方给出的Na…

【JavaSE】对象的比较

哈喽,大家好!我是保护小周ღ,本期为大家带来的是Java中自定义类型(对象)的三种比较方式,equals 方法, Comparable 泛型接口, Comparator 泛型接口 。在日常编程中,我们常常会需要比较的问题&…

cuda版本,pytorch(GPU)版本的选择和下载

cuda版本: 1.Nvidia控制面板里的cuda版本, 或使用nvidia-smi命令显示的cuda版本 是cuda的driver api版本 2.nvcc -V中的cuda版本,是cuda的runtime api版本,即cudatoolkit的版本 cudatoolkit的版本不能高于cuda driver api的版本&#xff…

23.2.28 Staffing System

员工管理系统功能介绍: 1)服务器负责管理所有员工表单(以数据库形式),其他客户端可通过网络连接服务器来查询员工表单。 2)需要账号密码登陆,其中需要区分管理员账号还是普通用户账号。 3&am…

聚观早报 | 苹果2024年放弃高通;腾讯回应进军类 ChatGPT

今日要闻:苹果2024年放弃高通;腾讯回应进军类 ChatGPT;小米发布无线AR眼镜探索版;50%的美国企业已在使用ChatGPT;Snap推出ChatGPT驱动的聊天机器人 苹果2024年放弃高通 高通公司 CEO 兼总裁克里斯蒂亚诺・安蒙&#xf…

Node.js 是个啥?

趣学 Node.js - 死月 - 掘金小册带你重新体悟 Node.js 之美。「趣学 Node.js」由死月撰写,1923人购买https://s.juejin.cn/ds/SYVvuDw/ 在这里,我们先装作对 Node.js 不了解,从头来过吧。你有没有假装不了解 Node.js 我不知道,但…

界面开发(2)--- 使用PyQt5制作用户登陆界面

使用PyQt5制作用户登陆界面 上篇文章已经介绍了如何配置PyQt5环境,这篇文章在此基础上展开,主要记录一下如何使用 PyQt5 制作用户登陆界面,并对一些基础操作进行介绍。 下面是具体步骤,一起来看看吧! 1. 打开 Pychar…

【IoT】2023裁员潮还在继续,构建规划能力也许是一剂良方

今天要分享的主题是华为的市场管理方法论。 市场管理这个词总体来说还是有些抽象,本质上来看或者说从个人的角度来看,其实就是一种规划的能力。 无论是创业,还是作为职场人,规划能力必将是你不可或缺的一种基础能力。 尤其是在这样…

Maven说明

目录 1.说明 2.详细说明 3.Maven模型 4.Maven常用的命令 5.Maven生命周期 6.Maven坐标 7.依赖管理与依赖范围 1.说明 Maven是专门用于管理和构建Java项目的工具,它是基于项目对象模型(POM)的概念,主要功能有: 提供了一套标准化的项目…

Ubuntu 下NGINX 的简单使用

1.NGINX的安装与卸载 1.1.安装NGINX apt-get install nginx1.2.NGINX操作命令 service nginx start #启动 service nginx reload #重新加载配置文件 service nginx restart #重启 service nginx status #查看运行状态 1.3.卸载NGINX apt-get remove nginx nginx-common #…

28 openEuler管理网络-配置主机名

文章目录28 openEuler管理网络-配置主机名28.1 简介28.2 使用hostnamectl配置主机名28.2.1 查看所有主机名28.2.2 设定所有主机名28.2.3 设定特定主机名28.2.4 清除特定主机名28.2.5 远程更改主机名28.3 使用nmcli配置主机名28 openEuler管理网络-配置主机名 28.1 简介 hostn…

XXL-JOB的基本使用

1、执行器 1.1下边配置执行器 下边配置执行器&#xff0c;执行器负责与调度中心通信接收调度中心发起的任务调度请求。 1、首先在媒资管理模块的service工程添加依赖&#xff0c;在项目的父工程已约定了版本2.3.1 XML <dependency><groupId>com.xuxueli</gro…