java String

String常用构造器

  • public String(): 空构造
  • public String(byte0 bytes): 把字节数组转成字符串
  • public String(byte0 bytes,int index,intlength): 把字节数组的一部分转成字符串
  • public String(char[]value): 把字符数组转成字符串
  • public String(char[] value,int index,int count): 把字符数组的一部分转成字符串
  • public String(String original): 把字符串常量值转成字符串

String常用API

判断方法

  • boolean equals(Object obj): 比较字符串的内容是否相同,区分大小写
  • boolean equalslgnoreCase(String str): 比较字符串的内容是否相同,忽略大小写
  • boolean contains(String str): 判断大字符串中是否包含小字符串
  • boolean startsWith(String str): 判断字符串是否以某个指定的字符串开头
  • boolean endswith(String str): 判断字符串是否以某个指定的字符串结尾
  • boolean isEmpty(): 判断字符串是否为空

获取方法

  • int length(): 获取字符串的长度
  • char charAt(int index): 获取指定索引位置的字符
  • int indexOf(int ch): 返回指定字符在此字符串中第一次出现处的索引,ch是字符的码表值
  • int indexOf(String str): 返回指定字符串在此字符串中第一次出现处的索引
  • int indexOf(int ch,int fromIndex): 返回指定字符在此字符串中从指定位置后第一次出现处的索引
  • int indexOf(String str,int fromIndex): 返回指定字符串在此字符串中从指定位置后第一次出现处的索引
  • int lastindexOf 同上

  • String substring(int start): 从指定位置开始截取字符串,默认到末尾
  • String substring(int start,int end): 从指定位置开始到指定位置结束截取字符串

转换方法

  • byte[] getBytes(): 把字符串转换为字节数组
  • char[] toCharArray(): 把字符串转换为字符数组
  • static String valueOf(char[]chs): 把字符数组转成字符串
  • static String valueOf(inti): 把int类型的数据转成字符串
    • 注意: String类的valueOf方法可以把任意类型的数据转成字符串
  • String toLowerCase(): 把字符串转成小写(了解)
  • String toUpperCase(): 把字符串转成大写
  • String concat(String str): 把字符串拼接

替换方法

  • String replace(char old,charnew): 将字符串中的一部分字符用新的代替
  • String replace(String old,String new): 将字符串中的一部分字符串用新的代替

切割方法

  • String[] split(Stringregex): 按照规则来切割字符串
  • String[] split(Stringregex,int limit): 按照规则来切割字符串 limit 表示总共切成几段(也就是数组的长度)

其他常用方法

  • trim(): 去除字符串前后的空格
  • int compareTo(String anotherString): 按字典顺序比较两个字符串(大小写)
  • int compareTolgnoreCase(String str): 按字典顺序比较两个字符串(忽路大小)

java对String的优化:

  1. 使用方式
  2. 性能

使用方式不用new

// 字面量
String s1 = "abc";
// new
String s2 = new String("123");

性能优化

问题

使用new方式创建对象时,即使对象属性完全一致也会创建多个对象,过于浪费资源

Person p1 = new Person(18);
Person p2 = new Person(18);
sout(p1 == p2); // false
解决方法

为了不浪费资源,我们可以声明一个static常量,但是String字符串的创建是无规律、大数量的,我们不可能声明那么多static常量

public static final Person P = new Person(18);

Person p1 = P;
Person p2 = P;
sout(p1 == p2); // true

将这些对象放进一个容器中(池化思想),用时判断是否存在后获取,及对象池,就像缓存

// 从对象池中获取
Person p1 = PersonPool.get(18);

当我们使用字面量创建字符串对象时,会从字符串常量池中寻找是否已创建,已创建则直接引用,反之在常量池中新建。

String不可变

String是什么

字符串就是一串连续的字符(char);

java面向对象所以简化了C语言中使用char[]数组表示字符串的复杂方法,将char[]进行封装,及String;

不可变是什么

解释一下不可变:

// 可变
Person p = new Person(18);
p.setAge(20);

// 不可变,无法修改String类中的属性
String s = "123";

有人会说,这不是可变的吗?

String s = "123";
s = "456"
sout(s); // 456

这样是变量重新引用了一个新的对象,类比到Person上如下:

Person p = new Person(18);
p = new Person(20);

String如何实现不可变

在java String源码中char数组private final char value[];

  1. 被private修饰
  2. 不暴露和提供任何修改字符数组value的方法,有的字符串操作都是返回新字符串对象,获取底层字符数组时都是复制一个新数组进行返回
  3. String类被final修饰,不可被继承,杜绝了继承后子类方法覆盖父类的可能
  4. value被final修饰,及value的引用不会被重新指向

String为什么要不可变

  1. 保护字符串常量池,如果String提供setValue()方法,调用该方法时,字符串常量池中对象的value属性也被改变,如果另一个变量指向该对象但这时该对象的属性已经改变,就会失去字符串常量池的作用。
  2. hash码不会变
  3. 线程安全

String StringBuilder StringBuffer StringJoiner

只有String重写了equals和hashCode方法

特点

适用场景

String

不可变,线程安全

操作量少或不需要操作数据

StringBuilder

可变,线程不安全

需要大量操作数据,且不用考虑线程安全

StringBuffer

可变,线程安全,性能较低

需要大量操作数据,且考虑线程安全

StringJoiner

可变,线程不安全

拼接字符串且有分隔符或前后缀

面试题

判断字符串地址是否

String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = "a" + "bc";// 编译时优化为 "abc"
String s5 = "a";
String s6 = s5 + "bc";// s5 是变量所以运行时才拿到,所以运行时拿到"a" + "bc",new一个StringBuilder调用append方法,toString后放入常量池

sout(s1 == s2);// true
sout(s1.equals(s2));// true

sout(s1 == s3);// false
sout(s1.equals(s3));// true

sout(s1 == s4);// true
sout(s1.equals(s4));// true

sout(s1 == s6);// false

new String("abc");创建了多少对象

  1. 字符串常量池中的对象
  • 当"abc"这个字符串字面量首次出现在代码中时,它会被放入字符串常量池(String Pool)。这个对象是由JVM自动创建的,用于避免相同字符串的重复创建和存储。
  1. 堆中的String对象
  • new String("abc")这一表达式会显式地创建一个新的String对象。即使"abc"已经存在于字符串常量池中,new关键字依然会在堆(Heap)中创建一个新的String对象,该对象的值是对常量池中"abc"的引用。

new String("a") + new String("b");

对象1: new StringBuilder()

对象2: new String(“a”)

对象3: 常量池中的"a"

对象4: new String(“b”)

对象5: 常量池中的"b"

深入剖析: StringBuilder 的 toString() 方法中有 new String(value, 0, count) ,

对象6 :new String(“ab”)

String str = "a" + "b";

"a" + "b" 在编译时,就已经编译为 ab, 被放到常量池中。
所以只有一个对象 :ab

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值