java的String类详解



String类表示字符串类型,String是java标准类库的预定义类,它是java的引用类型。 在java.lang包下,可以直接使用。
String类有final修饰,是最终类,不能被继承。



不可变字符串

String类是不可变类,这表明String对象包含的字符序列一旦创建就无法更改(没有setter方法)。不可变指的是对象不可变,但是String类型的引用变量可以指向不同的字符串对象

字符串常量池

一旦使用带双引号的字符串,就会在字符串常量池存储该字符串。这就相当于创建了一个字符串对象。比如:String s1 = “abc”,字符串"abc"就会被存储到字符串常量池中。
如果再次需要使用已经创建过的字符串,就直接让字符串的引用变量指向常量池中的字符串
比如:String s2 = “abc”; 因为前面已经在字符串常量池中创建了字符串"abc",所以系统会让s2直接指向该字符串,也就是s1和s2指向同一个字符串对象"abc"。

如果是用构造方法创建字符串对象,比如:String s3 = new String(“abc”); 此时会在堆内存新开辟一个空间存储这个String对象,对象内部的成员变量会记录常量池中"abc"字符串的地址。但是对象本身的地址是堆内存中新开辟的新地址

如果是通过构造器创建的String对象,想获取存储的字符串的常量池地址,可以使用intern实例方法:
public String intern(); 该方法可以获取字符串对象存储的字符序列的常量池地址。如果常量池没有该字符串对象存储的字符序列,就在常量池中创建该字符序列。

字符串常量池的位置在java7及其之后都是在堆内存中,java6及其以前字符串常量池在方法区



String类的继承关系

String类实现了三个接口:Serializable、Comparable、CharSequence接口



String类的底层实现

以前String类的底层是char数组,每个字符占2个字节。
从java9开始,String、StringBuffer和StringBuilder都是采用byte[]数组再加一个byte类型的code实例变量(用于标识编码类型)实现。因此每个字符只占1个字节。



创建String对象

String类是唯一一个有单独创建方式的类,它可以直接用双引号括起来的字符串来创建对象实例。比如"abc",这就相当于创建了一个String类的对象。
除此之外,String类也可以像普通类一样,用构造器创建对象。

介绍几个常见的构造器:

  1. String():构造一个空字符串的String对象。
  2. String(String original):创建一个和参数的字符串值相同的副本。
  3. String(char[] value):通过复制字符数组里的字符序列,创建一个字符串。
  4. public String(char[] value, int offset, int count):通过复制字符数组里的子字符序列,创建一个新的字符串。
  5. public String(byte[] bytes): 通过平台默认字符集,将bytes数组的元素序列转换为字符串。
  6. String(byte[] bytes, int offset, int length): 通过平台默认字符集,将bytes数组的子元素序列转换为对应的字符串。


字符串拼接

java的"+"运算符还可以做字符串的拼接
比如:String s1 = “abc” + “edf”; 这样s1的值为"abcdef"。
再比如:String s2 = “007” + 123; 这样s2的值为007123。注意,如果其中一个操作数是字符串,另一个操作数是任何类型都会被转换为字符串类型,比如这里123是int类型,会转换为字符串类型"123",再做拼接。

常见面试题

String s1 = "abc";
String s2 = "a" + "b" + "c";
System.out.println(s1 == s2);	// 结果为true

String s3 = "bc";
String s4 = "a" + s3;
System.out.println(s1 == s4);  // 结果为false

这是因为java有常量优化机制:如果等号右边的表达式全是常量,那么编译阶段右边的结果就会被计算出来。如果右边的结果在左边变量数据类型的范围内,就直接为其赋值,否则赋值失败。
所以,s2的值在编译阶段就已经确定了,为"abc",第二行代码相当于String s2 = “abc”,所以s2会和s1一起指向字符串常量池中的"abc",所以结果为true。
注意:String s2 = “a” + “b” + “c”; 实际上是创建了1个字符串对象"abc",在编译阶段时,三个单独的字符串就已经被合并为"abc"了,只有"abc"会被存储到常量池中。

当右边表达式存在变量时,编译期间不会存在常量优化机制。
对于String s4 = “a” + s3; 因为s3是一个变量。所以连接等号右边需要利用StringBuilder类,之后再调用它的toString方法返回一个String对象,这个对象有单独的地址,所以结果不等于"abc"。



String的常用方法

字符串是否相等

1.public boolean equals(Object anObject); 将该字符串与指定对象比较,如果二者包含的字符序列相等,则返回true;否则返回
false。
String类重写了Object类的equals方法,只看两个String对象存储的字符系列的值是否相等。

推荐写法:String s1 = “hello”; “hello”.equals(s1);
不推荐写法:String s1 = “hello”; s1.equals(“hello”);
这是因为s1的值如果是null,会产生异常,用字符串字面量做主调,可以避免这种异常。

要避免用==运算符比较两个字符串对象是否相等,等号运算符只是比较2个字符串引用变量指向的地址,而不是比较字符序列的值

2.public boolean equalsIgnoreCase(String anotherString); 如果希望比较字符序列时不考虑大小写,就用这个方法。

获取子串

public String substring(int beginIndex); 获取从beginIndex位置开始到整个字符串结束的子字符串(包括beginIndex)。
public String substring(int beginIndex, int endIndex); 获取从beginIndex位置开始到endIndex位置的子字符串(包括beginIndex,不包括endIndex)。

返回字符串的长度

public int length(); 返回该字符串对象的字符序列长度,准确说是Unicode代码单元的长度。

字符串的比较

public int compareTo(String anotherString); 按字典顺序比较两个字符串,返回正值、零、负值。

返回给定值的索引

public int indexOf(int ch); 返回给定值在字符串中第一次出现的索引
public int indexOf(int ch, int fromIndex); 返回给定值在字符串中第一次出现的索引,但是搜索的位置从索引fromIndex(包含fromIndex)开始
public int indexOf(String str); 返回给定子串在字符串中第一次出现的索引
public int indexOf(String str, int fromIndex); 返回给定子串在字符串中第一次出现的索引,但是搜索的位置从索引fromIndex(包含fromIndex)开始

public int lastIndexOf(int ch); 返回给定值在字符串中最后一次出现的索引
public int lastIndexOf(int ch, int fromIndex); 返回给定值在字符串中最后一次出现的索引,但是搜索的位置从索引fromIndex开始,往左边搜索
public int lastIndexOf(String str); 返回给定子串在字符串中最后一次出现的索引
public int lastIndexOf(String str, int fromIndex); 返回给定子串在字符串中最后一次出现的索引,但是搜索的位置从索引fromIndex开始,往左边搜索

如果没找到指定值,这些方法都会返回-1

转换大小写

public String toUpperCase(); 生成一个新的字符串,新字符串把字符串的所有字母转换为大写格式
public String toUpperCase(); 生成一个新的字符串,新字符串把字符串的所有字母转换为小写格式

返回给定索引的字符

public char charAt(int index); 返回字符串里,参数指定索引对应的字符

字符串替换

replace(CharSequence target, CharSequence replacement); 将字符串中包含的target子串全部替换为replacement字符串,替换是从左往右依次替换。

把字符串转换为数组

public char[] toCharArray(); 把字符串转换为新生成的对应字符数组。

public byte[] getBytes(); 使用平台的默认字符集,把字符串转换为byte序列,并存储到一个新的byte数组中。

去字符串空白

public String trim(); 返回一个新的字符串,去掉原字符串开头和结尾的空白

字符串连接

public String concat(String str); 将指定字符串链接到字符串的结尾,并返回连接后的字符串

格式化字符串输出

public static String format(String format, Object… args); 使用指定的字符串和参数返回一个格式化后的新字符串。
它和C语言的printf是一样的用法。

字符串切割

public String[] split(String regex); 根据正则表达式的规则把字符串拆分为一个字符串数组。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值