一、String类基本概念
1.1 介绍
public final class String
extends Object
implements Serializable, Comparable<String>, CharSequence
复制代码
String 实际上与 System 类和 Scanner 类一样,都是 Java 库中一个预定义的类。String类型不是基本类型,而是引用类型(reference type)。
- String类:代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
- String是一个final类,代表不可变的字符序列。
- 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
- String对象的字符内容是存储在一个字符数组value[]中的。
- 实现了Serializable接口:表示字符串是支持序列化的。
- 实现了Comparable接口:表示String可以比较大小。
1.2 构造字符串
String string1 = "abc";
String string2 = new String("abc");
char[] a = {"a","b"};
String string3 = new String(a);
char[] a = {"a","b","c","d","e"};
String string4 = new String(a,0,3);
复制代码

tips: String str1 = “abc”;与String str2 = new String(“abc”);的区别?
- 字符串常量存储在字符串常量池,目的是共享
- 字符串非常量对象存储在堆中。
1.3 不可变字符串与限定字符串
String 对象是不可变的,它的内容是不能改变的。
①
String s1 = "abc";//字面量的定义方式
String s2 = "abc";
s1 = "hello";
System.out.println(s1 == s2);//比较s1和s2的地址值 false
System.out.println(s1);//hello
System.out.println(s2);//abc
复制代码
上面的代码并没有改变字符串s1的内容,。第一条语句创建了一个内容为”abc” 的 String 对象,并将其引用赋值给s1.第三条语句创建了一个内容为”hello”的新 String 对象,并将其引用赋值给 s1。赋值后第一个 String 对象仍然存在,但是不能再访问它,因为变量 s1 现在指向了新的对象。如下图

②
String s3 = "abc";
s3 += "def";
System.out.println(s3);//abcdef
System.out.println(s2);
String s4 = "abc";
String s5 = s4.replace('a', 'm');
System.out.println(s4);//abc
System.out.println(s5);//mbc
复制代码
上面代码进行连接操作时,重新创建了一个”abcedf”的对象。replace()方法修改指定字符或字符串时,也重新创建了一个对象,并不会改变原来的字符串。
- 字符串常量池中是不会存储相同内容的字符串的。
- 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
- 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
- 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
③
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s6);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false
String s8 = s6.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop”
System.out.println(s3 == s8);//true
复制代码

- 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
- 只要其中有一个是变量,结果就在堆中。
- 如果拼接的结果调用intern()方法,返回值就在常量池中
- 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
④
//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false
System.out.println("***********************");
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);
System.out.println(p1.name.equals(p2.name));//true
System.out.println(p1.name == p2.name);//true
p1.name = "Jerry";
System.out.println(p2.name);//Tom
复制代码

tips:String s = new String(“abc”);方式创建对象,在内存中创建了几个对象? 两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:”abc”
二、字符串的操作
2.1 字符串的比较
- boolean equals(Object obj):比较字符串的内容是否相同
- boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大 小写
- String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
- int compareTo(String anotherString):比较两个字符串的大小
- 如果参数字符串等于此字符串,则值为0 ;
- 如果这个字符串的字典比字符串参数小,这个值小于0,
- 如果此字符串的字典大小超过字符串参数,则值大于0 。
- String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
2.2 字符串的替换和分隔
- String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
- String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
- String trim():返回字符串的副本,忽略前导空白和尾部空白
- String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
- boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
- String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
- String replaceAll(String regex, String replacement) : 诗 用 给 定 的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
- String replaceFirst(String regex, String replacement) : 诗 用 给 定 的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
- boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
- String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
- String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中
- String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
- String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
- char charAt(int index): 返回某索引处的字符return value[index]
2.3 字符串与数组之间的转换
1.String与字符数组转换 ① String –> char[]:
- 调用String的toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。
- 调用 public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法。
② char[] –> String:调用String的构造器
- String(char[]):字符数组中的全部字符
- String(char[],int offset,int length):部分字符创建字符串
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
System.out.println(charArray[i]);
}
char[] arr = new char[]{'h','e','l','l','o'};
String str2 = new String(arr);
System.out.println(str2);
复制代码
2.String与字节数组转换 编码:String –> byte[]:调用String的getBytes() 解码:byte[] –> String:调用String的构造器
2.4 将字符和数值转换为字符串

1.将String类的数据转换为基本数据类型
① 通过包装类的构造器实现:int i = new Integer(“12”); ② 通过包装类的parseXxx(String s)静态方法:Float f = Float.parseFloat(“12.1”);
String str1 = "123";
int num2 = Integer.parseInt(str1);
System.out.println(num2 + 1);
复制代码
2.将基本数据类型转换为String类 ①调用字符串 重载 的valueOf()方法:String str = String.valueOf(2.34f); ② 更直接的方式:String intStr = 5 + ” “;
int num1 = 10;
//方式1:连接运算
String str1 = num1 + "";
//方式2:调用String的valueOf(Xxx xxx)
float f1 = 12.3f;
String str2 = String.valueOf(f1);//"12.3"
Double d1 = new Double(12.4);
String str3 = String.valueOf(d1);
System.out.println(str2);
System.out.println(str3);//"12.4"
复制代码
3.将char类型转换为int类型
char ch = '9';
if(Character.isDigit(ch)){
int num = Integer.parseInt(String.valueOf(ch)); }
char ch = '9';
if(Character.isDigit(ch)){
int num = (int)ch - (int)('0');
复制代码
4.包装类与基本数据类型的互换
int num1 = 10;
// System.out.println(num1.toString());
Integer in1 = new Integer(num1);
System.out.println(in1.toString());
Integer in2 = new Integer("123");
System.out.println(in2.toString());
//报异常
// Integer in3 = new Integer("123abc");
// System.out.println(in3.toString());
Float f1 = new Float(12.3f);
Float f2 = new Float("12.3");
System.out.println(f1);
System.out.println(f2);
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean("TrUe");
System.out.println(b2);//true
Boolean b3 = new Boolean("true123");
System.out.println(b3);//false
复制代码
5.JDK1.5之后,支持自动装箱,自动拆箱。但类型必须匹配
//自动装箱:基本数据类型 --->包装类
int num2 = 10;
Integer in1 = num2;//自动装箱
boolean b1 = true;
Boolean b2 = b1;//自动装箱
//自动拆箱:包装类--->基本数据类型
System.out.println(in1.toString());
int num3 = in1;//自动拆箱
复制代码
三、StringBuilder 和 StringBuffer 类
3.1 介绍
StringBuilder 和 StringBuffer 类似于 String 类,区别在于 String 类是不可改变的。 — 般来说,只要使用字符串的地方,都可以使用StringBuilder/StringBuffer’类。StringBuilder/StringBuffer类比 String类更灵活。可以给一个 StringBuilder 或 String Buffer 中添加、插入或添加新的内容,而不产生新的对象。 StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器:
- StringBuffer():初始容量为16的字符串缓冲区
- StringBuffer(int size):构造指定容量的字符串缓冲区
- StringBuffer(String str):将内容初始化为指定字符串内容
String s = new String("我喜欢学习");
StringBuffer buffer = new StringBuffer("我喜欢学习");
buffer.append("数学");
复制代码
3.2 StringBuilder 和 StringBuffer 类的区别
StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且 提供相关功能的方法也一样
- String:不可变的字符序列;底层使用char[]存储
- StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储
- StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储
3.3 StringBuffer类的常用方法
- StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
- StringBuffer delete(int start,int end):删除指定位置的内容
- StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
- StringBuffer insert(int offset, xxx):在指定位置插入xxx
- StringBuffer reverse() :把当前字符序列逆转
- public int indexOf(String str)
- public String substring(int start,int end):返回一个从start开始到end索引结束的左闭右开区间的子字符串
- public int length()
- public char charAt(int n )
- public void setCharAt(int n ,char ch)
StringBuffer s1 = new StringBuffer("abc");
s1.append(1);
s1.append('1');
System.out.println(s1);//abc11
// s1.delete(2,4);
// s1.replace(2,4,"hello");
// s1.insert(2,false);
// s1.reverse();
String s2 = s1.substring(1, 3);
System.out.println(s1);// abc11
System.out.println(s1.length());//5
System.out.println(s2);//bc
作者:马走日lx
链接: