字符串
API
API(Application Programming Interface):应用程序编程接口
简单理解:API就是别人已经写好的东西,我们不需要自己编写,直接使用即可
Java API:指的就是JDK中提供的各种功能的Java类
这些类将底层的实现封装了起来,我们不需要关心这些类时如何实现的,只需要学习这些类如何使用即可
API帮助文档:帮助开发人员更好的使用API和查询API的一个工具
String概述
java.lang.String 类代表字符串,Java程序中的所有字符串文字(例如“abc”)都为此类的对象
String的注意点
字符串的内容时不会发生改变的,它的对象在创建后不能被更改
总结:
- String 是 Java定义好的一个类,定义在java.lang包中,所以使用的时候不需要导包
- Java 程序中的所有字符串文字(例如“asdfgh”)都被视为此类的对象
- 字符串不可变,它们的值在创建后不能被更改
String构造方法代码实现和内存分析
创建String对象的两种方式
- 直接赋值
String name = "aaaa";
- new
| 构造方法 | 说明 |
|---|---|
| public String() | 创建空白字符串,不含任何内容 |
| public String(String original) | 根据传入的字符串,创建字符串对象 |
| public String(char[] chs) | 根据字符数组,创建字符串对象 |
| public String(byte[] chs) | 根据字节数组,创建字符串对象 |
String s1 = new String();
String s2 = new String("asdf")
char[] chars = {'a', 'b', 'c'};
String s3 = new String(chars);
byte[] bytes = {97, 98, 99, 100};
String s4 = new String(bytes);
内存分析
除了new出来的字符串,直接赋值出来的字符串出现在 StringTable 串池中
注意:StringTable(串池)在JDK7版本开始,从方法区挪到了堆内存
-
当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在
-
不存在:创建新的
-
存在:复用
-
优点:节约内存
-
-
当使用new创建时,每new一个就会在堆区开辟一个内存
字符串的比较
== 号比的到底是什么?
- 基本数据类型比较的是数据值
- 引用数据类型比较的是地址值
字符串比较
- boolean equals(要比较的字符串)
- 完全一样结果才是true,否则为false
- boolean equalslgnoreCase(要比较的字符串)
- 忽略大小写的比较
遍历字符串
- public char charAt(int index):根据索引返回字符
- public int length():返回此字符串的长度
- public char[] toCharArray():将字符串拆开返回字符数组
- 数组的长度:数组名.length
- 字符串的长度:字符串对象.length()
截取
- String substring(int beginLindex, int endIndex):截取
- 注意点:包头不包尾,包左不包右,只有返回值才是截取的小串
- String substring(int beginIndex):截取到末尾
替换
-
String replace(旧值, 新值):替换
- 注意点:只有返回值才是替换之后的结果
- 可以通过循环替换字符串数组里的每个字符串
talk = talk.replace(arr[i], "***");
StringBuilder
StringBuilder可以看成一个容器,创建之后里面的内容是可变的
- 作用:提高字符串的操作效率
StringBuilder构造方法
| 方法名 | 说明 |
|---|---|
| public StringBulider() | 创建一个空白可变字符串对象,不含有任何内容 |
| public StringBulider(String str) | 根据字符串的内容,来创建可变字符串对象 |
StringBuilder sb = new StringBuilder("abc");
StringBuilder常用方法
| 方法名 | 说明 |
|---|---|
| public StringBuilder append(任意类型) | 添加数据,并返回对象本身 |
| public StringBuilder reverse() | 反转容器中的内容 |
| public int length() | 返回长度(字符出现的个数) |
| public String toString | 通过toString()就可以把StringBuilder转换为String |
- 将键盘录入的转换为StringBuilder类型
StringBuilder s = new StringBuilder(sc.next());
使用StringBuilder的场景:
- 字符串的拼接
- 字符串的反转
StringJoiner
- StringJoiner跟StringBuilder一样,也可以看成一个容器,创建之后里面的内容是可变的
- 作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用
- JDK8出现的
StringJoiner的构造方法
| 方法名 | 说明 |
|---|---|
| public StringJoiner(间隔符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号 |
| public StringJoiner(间隔符号, 开始符号, 结束符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号 |
StringJoiner sj = new StringJoiner("---"); //1---2---3
StringJoiner sj = new StringJoiner(", ", "[", "]"); //[1, 2, 3]
StringJoiner的成员方法
| 方法名 | 说明 |
|---|---|
| public StringJoiner add(添加的内容) | 添加数据,并返回对象本身 |
| public int length() | 返回长度(字符出现的个数,间隔符什么的也算) |
| public String toString() | 返回一个字符串(该字符串就是拼接之后的结果) |
总结
- String
标识字符串的类,定义了很多操作字符串的方法
- StringBuilder
一个可变的操作字符串的容器
可以高效的拼接字符串,还可以将容器里面的内容反转
- StringJoiner
JDK8出现的一个可变的操作字符串的容器,可以高效、方便的拼接字符串
字符串相关类的底层原理
字符串存储的内存原理
- 直接赋值会服复用字符串常量池中的
- new出来的不会复用,而是开辟一个新的空间
==号比较的到底是什么
- 基本数据类型比较数据值
- 引用数据类型比较地址值
字符串拼接的底层原理
- 拼接的时候没有变量,都是字符串
- 触发字符串的优化机制,在编译的时候就已经是最终的结果了
- 拼接的时候有变量
- JDK8以前底层会使用StringBuilder
- 系统底层会自动创建一个StringBuilder对象,然后再调用其append方法完成拼接
- 拼接后,再调用其toString方法转换为String类型,而toString方法的底层是直接new了一个字符串对象
- JDK8及以后
- 系统会预估字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生了一个新的字符串
- 在内存中创建了很多对象,浪费空间,时间也非常慢
- JDK8以前底层会使用StringBuilder
- 总结:
- 如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串
- 如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存
- 如果很多字符串变量拼接,不要直接+,在底层会创建多个对象,浪费时间,浪费性能
StringBuilder提高效率原理
- 所有要拼接的内容都会往StringBuilder中放,不会创建很多无用的空间,浪费内存
StringBuilder源码分析
- 默认创建一个长度为16的字节数组
- 添加的内容长度小于16,直接存
- 添加的内容大于16会扩容(原来容量*2+2)
- 如果扩容之后还不够,以实际长度为准(最大到int的最大值)