Java字符串

97 阅读6分钟

字符串

API

API(Application Programming Interface):应用程序编程接口

简单理解:API就是别人已经写好的东西,我们不需要自己编写,直接使用即可

Java API:指的就是JDK中提供的各种功能的Java类

这些类将底层的实现封装了起来,我们不需要关心这些类时如何实现的,只需要学习这些类如何使用即可

API帮助文档:帮助开发人员更好的使用API和查询API的一个工具

String概述

java.lang.String 类代表字符串,Java程序中的所有字符串文字(例如“abc”)都为此类的对象

String的注意点

字符串的内容时不会发生改变的,它的对象在创建后不能被更改

总结

  1. String 是 Java定义好的一个类,定义在java.lang包中,所以使用的时候不需要导包
  2. Java 程序中的所有字符串文字(例如“asdfgh”)都被视为此类的对象
  3. 字符串不可变,它们的值在创建后不能被更改

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的场景:

  1. 字符串的拼接
  2. 字符串的反转

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及以后
      • 系统会预估字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生了一个新的字符串
    • 在内存中创建了很多对象,浪费空间,时间也非常慢
  • 总结:
    • 如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串
    • 如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存
    • 如果很多字符串变量拼接,不要直接+,在底层会创建多个对象,浪费时间,浪费性能

StringBuilder提高效率原理

  • 所有要拼接的内容都会往StringBuilder中放,不会创建很多无用的空间,浪费内存

StringBuilder源码分析

  • 默认创建一个长度为16的字节数组
  • 添加的内容长度小于16,直接存
  • 添加的内容大于16会扩容(原来容量*2+2)
  • 如果扩容之后还不够,以实际长度为准(最大到int的最大值)