首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >String 详解以及内存分析

String 详解以及内存分析

作者头像
帅飞
发布于 2019-01-22 08:30:27
发布于 2019-01-22 08:30:27
8610
举报
文章被收录于专栏:Java知其所以然Java知其所以然

字符串(java.lang.String 类)的使用

Java 字符串就是 Unicode 字符序列,例如串 “Java” 就是 4 个 Unicode 字符 J,a,v,a 组成的。

Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个预定义的类String,每个用双引号括起来的字符串都是 String 类的一个实例。

String e = “” ; // an empty string

String greeting = “Hello World”;

Java 允许使用符号 "+" 把两个字符串连接起来

String s1 = “Hello”;

String s2 = “World!”;

符号 “+” 把两个字符串按给定的顺序连接在一起,并且是完全按照给定的形式。

当 “+” 运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串然后再进行连接

int age = 18;

String s = "age is" + age; //s赋值为age is 18

这种特性通常被用在输出语句中:

System.out.println(“age is” + age);

字符串类常用的方法

char charAt(int index)

返回字符串中第 index 个字符。

boolean equals(String other)

如果字符串与 other 相等,返回 true。因为 String 类重写了 equals 方法。

boolean equalsIgnoreCase(String other)

如果字符串与 other 相等(忽略大小写),则返回 true

int indexOf(String str) lastIndexOf()

返回与 str 匹配的第一个字符串的开始位置,该位置从 0 开始计算,如果原始串中不存在 str,返回 -1。

int indexOf(String str,int fromIndex)

返回与 str 匹配的第一个字符串的开始位置,该位置从 fromIndex 开始计算,如果原始串中不存在 str,返回 -1。

int length()

返回字符串的长度。

String replace(char oldChar,char newChar)

返回一个新串,它是通过用 newChar 替换此字符串中出现的所有oldChar而生成的

boolean startsWith(String prefix)

如果字符串以prefix开始,则返回 true

boolean endsWith(String prefix)

如果字符串以 prefix 结尾,则返回 true

String substring(int beginIndex)

返回一个新字符串,该串包含从原始字符串 beginIndex 到串尾的所有字符

String substring(int beginIndex,int endIndex)

返回一个新字符串,该串包含从原始字符串 beginIndex 到串尾或 endIndex-1 的所有字符

String toLowerCase()

返回一个新字符串,该串将原始字符串中的所有大写字母改成小写字母

String toUpperCase()

返回一个新字符串,该串将原始字符串中的所有小写字母改成大写字母

String trim()

返回一个新字符串,该串删除了原始字符串头部和尾部的空格 注:在 Java 中某个索引区间进行一些操作的方法,索引取值范围一般都是包头不包尾,就拿上面的 String substring(int beginIndex,int endIndex) 来说,它是截取子串 从 beginIndex 开始 到 endIndex - 1 结束。

字符串相等的判断

equals 方法用来检测两个字符串内容是否相等。如果字符串 s 和 t 内容相等,则s.equals(t) 返回 true,否则返回 false.

s 和 t 既可以是字符串变量,也可以是字符串常量,例如: “Hello”.equals(t);

要测试两个字符串除了大小写区别外是否是相等的,需要使用 equalsIgnoreCase 方法,例如:

“Hello”.equalsIgnoreCase(“hellO”); //true

判断字符串是否相等不要使用 "==","=="比较是引用是否相等(是否为同一个对象)

String 内存分析

创建了 4 个对象

分析:

先去 "字符串池" 中找 "a", 没有找到,在 "字符串池" 中创建 "a" 这个String 对象,先去先去 "字符串池" 中找 "a",找到 "a", new String("a") 在堆中创建一个 String 对象(因为 new 关键字一出现,肯定会创建一个对象)。

循环

i = 0; gh = "a0"; 先去 "字符串池" 中找 "a0", 没有找到,在 "字符串池" 中创建 "a0" 这个String 对象

i = 1; gh = "a01"; 先去 "字符串池" 中找 "a01", 没有找到,在 "字符串池" 中创建 "a01" 这个String 对象

思考

String 不是不可变对象吗?那为什么可以字符串拼接啊?你是在逗我吗?

String JDK 源码

final 修饰了 String 类,使得 String 类不可被继承。

final 修饰了 char value[],使得字符串的值不可以改变。

但是 final 并没有修饰 String 的引用,即 final String str;

这样的话,字符串的引用可以改变指向,比如上面的字符串拼接,gh 刚开始指向 "a",随着拼接又指向了 "a0"、"a01"。实际上这个过程中只是 gh 这个引用的指向在改变,"a"、"a0"、"a01" 并没有被改变。

注:这是我画的几个草图为了帮助大家理解,实际上字符串的内存分析要比这个复杂点。

明显可以看出来(在字符串拼接的过程中,创建出来的这些中间 String 对象并不会被回收),"+" 字符串拼接对于内存的浪费比较大,如果是服务器端编程,多线程将会很浪费空间。 字符串拼接存在的问题

要得到上面的 s4,就会 s1 和 s2 拼接生成临时一个 String 对象 t1,内容为 "hello word",然后有 t1 和 s3 拼接生成最终我们需要的 s4 对象,这其中,产生了一个中间的 t1,而且 t1 创建之后,没有主动回收,势必会占一定的空间。如果是一个很多(尤其是一个部署到服务器上的项目,每个用户开一个线程,那用户越来越多的时候这个性能的损耗就很明显了)字符串的拼接,那么代价就更大了,性能一下会降低很多。

一个 Java 程序如果想运行起来,需要经过两个时期,编译时和运行时。在编译时,Java 编译器(Compiler)将 java 文件转换成字节码。在运行时,Java 虚拟机(JVM)运行编译时生成的字节码。通过这样两个时期,Java 做到了所谓的一处编译,处处运行。

早期的版本中,字符串拼接是会在常量池创建对象的,所以不少编程规范都会说不要直接用加号去拼接字符串,因为老是去常量池创建对象的话,开销也不小。

在 jdk5.0 之后 java 对字符串拼接做了编译器的优化处理

当 Java 编译器遇到字符串拼接的时候,会创建一个 StringBuilder 对象,后面的拼接,实际上是调用 StringBuilder 对象的 append 方法。这样就不会有我们上面担心的问题了。

分析上边这个代码,看起来没毛病。但是这里面有一个很重要的就是 StringBuilder 对象创建发生在循环之间,也就是意味着有多少次循环会创建多少个 StringBuilder 对象,这样明显不好。稍微优化一下。

StringBuilder 对象的创建在循坏外面,这样就只创建了一个对象,比较好。 总结

  1. 我们在循环体中需要尽量避免隐式或者显式创建 StringBuilder。 也就是说平时简单的拼接,直接 "+" 号拼接就行;如果要用循环,就在外面 new 个StringBuilder 对象,然后循环里 append 拼接就行了好。
  2. 其实对于循坏来说,尽量避免在循坏里创建对象,可以将创建对象这个操作放在循坏外面,这样我们就让这个对象达到复用了。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-07-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java知其所以然 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java基础专题(三):字符串
从概念上来讲,Java字符串就是Unicode字符序列。例如,"Java\u2122" 由5个Unicode字符J,a,v,a,和 ™。Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,叫做String。每个用双引号括起来的字符串都是String类的一个实例。
山禾说
2019/01/21
6420
JAVA | 聚焦 String 的常见用法与底层内存原理
API(Application Programming Interface)应用程序编程接口
钮祜禄.爱因斯晨
2025/06/11
1350
JAVA | 聚焦 String 的常见用法与底层内存原理
String 既然能这样性能调优,我直呼内行(文末送书)
爱她,不能只会简单一起玩耍,要深入了解String 的内心深处,做一个「心有猛虎,细嗅蔷薇」的暖男。
码哥字节
2021/11/08
4760
String 既然能这样性能调优,我直呼内行(文末送书)
《Java从入门到失业》第四章:类和对象(4.2):String类
       这一节,我们学习第一个类:String类。String翻译成汉语就是“字符串”,是字符的序列。我们知道,在Java中,默认采用Unicode字符集,因此字符串就是Unicode字符的序列。例如字符串“Java大失叔”,就是由7个Unicode字符‘J’、‘a’、‘v’、‘a’、‘大’、‘失’、‘叔’组成。在JDK中,把字符串抽象成一个类String提供给我们使用。String类在java.lang包中。
用户7801119
2020/09/27
5170
详述 Java 语言中的 String、StringBuffer 和 StringBuilder 的使用方法及区别
1 简介 在 Java 语言中,共有 8 个基本的数据类型,分别为:byte、short、int、long、float、double、boolean和char,其中char类型用于表示单个字符,例如 a、b、c 、A、B、C、& 这些大小写字母或者特殊字符等等。在实际的编程中,单个的字符并没有我们想象中用的那么频繁,反而是多个字符组成的“字符串”更为常见,但是在基本的数据类型中,并没有字符串这种数据类型。为了解决这个问题,Java 语言为我们提供了一个被final关键字修饰的类 String,她就表示字符串
CG国斌
2018/01/26
8240
java基础(八)
JAVA并不是纯面向对象的语言。Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的。
Vincent-yuan
2020/06/11
4630
java基础(八)
小钻一下 String 源码
我正坐在沙发上津津有味地读刘欣大佬的《码农翻身》——Java 帝国这一章,门铃响了。起身打开门一看,是三妹,她从学校回来了。
沉默王二
2021/06/16
2990
String、StringBuilder、StringBuffer区别;String底层详解,实例化、拼接、比较;String为什么不可变
String是Java中的一个内置类,Immutable不可变,即一旦创建String对象,它的值就不能被更改。对String对象的replace、subString、toLowerCase等操作都会返回一个新String对象,故每次操作String时 性能较低、浪费内存空间
寻求出路的程序媛
2024/04/21
3730
String、StringBuilder、StringBuffer区别;String底层详解,实例化、拼接、比较;String为什么不可变
面试常备,字符串三剑客 String、StringBuffer、StringBuilder
字符串操作毫无疑问是计算机程序设计中最常见的行为之一,在 Java 大展拳脚的 Web 系统中更是如此。
飞天小牛肉
2021/02/26
4641
面试常备,字符串三剑客 String、StringBuffer、StringBuilder
深入理解Java中的String
想要了解一个类,最好的办法就是看这个类的实现源代码,来看一下String类的源码:
lyb-geek
2019/01/08
6620
零基础学Java(4)字符串
从概念上讲,Java字符串就是Unicode字符序列。例如,字符串"Java\u2122"由5个Unicode字符J、a、v、a和™组成。Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,很自然地叫做String。每个双引号括起来的字符串都是String类中的一个实例
全栈程序员站长
2022/09/19
4130
Java String 类
String类是Java中表示字符串的类。它是不可变的,一旦创建了一个字符串对象,就无法修改它。
久绊A
2023/03/24
3560
Java-String那些事
Java-String那些事 String对于广大程序员来说,并不陌生,是我们在编写程序中经常使用到的对象。但是,你真的对String了解吗,使用的方式对吗? 接下来,笔者就对String来进行全面的解析,让你对String有更深入的了解! 更重要的是,面试的时候,虐虐面试官! String源码(截取) public final class String implements java.io.Serializable, Comparable<String>, CharSequence { pri
贾博岩
2018/05/11
6050
Java基础-常用类(二)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
cwl_java
2019/11/12
3830
阿里一面:如何将重复性比较高的 String 类型的地址信息从 20GB 降到几百兆?
这次应该是互联网及软件行业的第三次寒潮,大家在寒潮中一定要继续保持学习,寒潮挺过去以后还是会迎来新的发展机遇。
码哥字节
2024/04/13
1570
阿里一面:如何将重复性比较高的 String 类型的地址信息从 20GB 降到几百兆?
深入理解String,StringBuilder,StringBuffer
从上面的三个方法可以看出,无论是subString、concat还是replace操作都不是在原有的字符串上进行的,而是重新生成了一个新的字符串对象。也就是说进行这些操作后,最原始的字符串并没有被改变。
yesr
2019/03/20
5480
深入理解String,StringBuilder,StringBuffer
一起学JAVA API Object String StringBuffer/StringBuilder
大家好,又见面了,我是你们的朋友全栈君。 1 前言 亲爱的小伙伴萌,目前我们看到的是Java基础部分的一个新的部分API,这是个啥,又能做啥呢? 其实可以概括成一句话:帮助我们站在巨人的肩膀上
全栈程序员站长
2022/09/01
2510
一起学JAVA API Object String StringBuffer/StringBuilder
一文看完String的前世今生,内容有点多,请耐心看完!
String字符串作为一种引用类型,在Java中的地位举足轻重,也是代码中出现频率最高的一种数据结构,因此,我们需要像分析Object一样,将String作为一个topic,单独拿出来总结,这里面涉及到字符串的不可变性,字符串拼接、存储、比较、截取以及StringBuffer,StringBuilder区别等。
JavaBuild
2024/05/27
1510
一文看完String的前世今生,内容有点多,请耐心看完!
一文读懂字符串String
String在java中特别常用,但小伙伴儿们对String真的彻底了解了吗?今天跟着小堂我一起盘它、弄懂它。
编程识堂
2023/05/24
6170
一文读懂字符串String
从认识String类,到走进String类的世界
作为一个常用的数据类型,跟随小编一同进入String的学习吧,领略String的一些用法。
学无止尽5
2024/11/29
4520
从认识String类,到走进String类的世界
推荐阅读
相关推荐
Java基础专题(三):字符串
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档