在 C 语言中已经涉及到字符串了,但是在 C 语言中要表示字符串只能使用字符数组或者字符指针可以使用标准库供的字符串系列函数完成大部分操作,字符串应用又非常广泛,因此Java 语言专门提供了 String 类。
1. 常用方法
1.1 字符串构造
常用的三种构造方法:
public static void main(String[] args) {
// 常量串构造
String s1 = "hello world";
System.out.println(s1);
// newString对象
String s2 = new String("hello world");
System.out.println(s1);
// 使用字符数组进行构造
char[] array = {'h','e','l','l','o','w','o','r','l','d'};
String s3 = new String(array);
System.out.println(s1);
}
1. String是引用类型,可以把他看成C语言中的指针,内部并不存储字符串本身,JDK8地string是char类型的,JDK17是byte类型的
2. 在Java中“”引起来的也是String类型对象。
System.out.println("hello".length());
byte[] array2 = new byte[] {'h','e','l','l','o','b'}; String s4 = new String(array2); System.out.println(s4);
1.1 String对象的比较
1.1.1 ==比较是否引用同一个对象
基本类型比较变量值,引用类型比较引用的地址
int a = 101; int b = 201; int c = 101; // 对于基本类型变量,==比较两个变量中存储的值是否相同 System.out.println(a == b); // false System.out.println(a == c); // true // 对于引用类型变量,==比较两个引用变量引用的是否为同一个对象 String s1 = new String("hello"); String s2 = new String("hello"); String s3 = new String("world"); String s4 = s1; System.out.println(s1 == s2); // false System.out.println(s2 == s3); // false System.out.println(s1 == s4); // true
引用只能指向对象
1.1.2 boolean equals(Object anObject) 方法
按照字符大小的顺序来比较,也就是按照字典序比较
String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照引用内容是否相同进行比较
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("H213ello");
// s1、s2、s3引用的是三个不同对象,因此全部为false
System.out.println(s1 == s2); // false
System.out.println(s1 == s3); // false
// equals比较:String对象中的逐个字符
// 虽然s1与s2引用的不是同一个对象,但是两个对象中放置的内容相同,因此输出true
// s1与s3引用的不是同一个对象,而且两个对象中内容也不同,因此输出false
System.out.println(s1.equals(s2)); // true
System.out.println(s1.equals(s3)); // false
1.1.3 int compareTo(String s) 方法
与compareToIgnoreCase方法相同,但是有大小写之分
String s1 = new String("abc");
String s2 = new String("ac");
String s3 = new String("ABc");
String s4 = new String("abcdef");
String s5 = new String("AbC");
System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1
System.out.println(s1.compareTo(s3)); // 不同输出字符差值32
System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3
System.out.println(s1.compareTo(s5));不同输出字符差值32
1.1.4 int compareToIgnoreCase(String str) 方法
与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:
1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值2. 如果前 k 个字符相等 (k 为两个字符长度最小值 ) ,返回值两个字符串长度差值3. 完全相同则返回0,注意,没有大小写之分
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = new String("ac");
String s3 = new String("ABc");
String s4 = new String("abcdef");
System.out.println(s1.compareToIgnoreCase(s2)); // 不同输出字符差值-1
System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0
System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出长度差值 -3
}
1.2 字符串查找
注意,编译器会将单引号认为是字符,双引号是字符串
1.2.1 char charAt(int index)
返回 index 位置上字符,如果 index 为负数或者越界,则抛出异常
String s = "aaab";
System.out.println(s.charAt(0)); // a
1.2.2 int indexOf(int ch)
返回ch第一次出现的位置,没有返回-1
String s = "aaab";
System.out.println(s.indexOf('b'));//3
1.2.3 indexOf(int ch, int fromIndex)
从 fromIndex 位置开始找 ch 第一次出现的位置,没有则返回-1
String s = "aaab";
System.out.println(s.indexOf('b',3));// 3
1.2.4 int indexOf(String str)
返回 str 第一次出现的位置,没有返回 -1
String s = "aaab";
System.out.println(s.indexOf("AB"));//-1
System.out.println(s.indexOf("a"));//0
System.out.println(s.indexOf("aa"));//0
System.out.println(s.indexOf("aaa"));//0
1.2.5 int indexOf(String str, int fromIndex)
从 fromIndex 位置开始找 str 第一次出现的位置,没有返回 -1
String s = "aaababbabab";
System.out.println(s.indexOf("ab",3));//4
1.2.6 int lastIndexOf(int ch)
从后往前找,返回ch第一次出现的位置,没有返回-1
String s = "aaababbabab";
System.out.println(s.lastIndexOf('b'));//10
1.2.7 int lastIndexOf(int ch, int fromIndex)
String s = "aaababbabab";
System.out.println(s.lastIndexOf('b',5));//5
1.2.8 int lastIndexOf(String str)
从后往前找,返回str第一次出现的位置,没有返回-1
String s = "aaababbabab";
System.out.println(s.lastIndexOf("abba"));//4
1.2.9 int lastIndexOf(String str, int fromIndex)
从fromIndex位置开始从后往前找 str 第一次出现的位置,没有则返回-1
String s = "aabaaaaaaabab"; System.out.println(s.lastIndexOf("abba",1));//-1
1.3 转化
1.3.1 数值和字符串转化
// 数字转字符串
int a =1234;
String s1 = String.valueOf(a);
String s2 = String.valueOf(12.34);
String s3 = String.valueOf(true);
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
// 字符串转数字
int data1 = Integer.parseInt("1234");
double data2 = Double.parseDouble("12.34");
System.out.println(data1);
System.out.println(data2);
1.3.2 大小写转换
String s1 = "heLlo";
String s2 = "HELLO";
// 小写转大写
System.out.println(s1.toUpperCase());
// 大写转小写
System.out.println(s2.toLowerCase());
1.3.2 字符串转数组
String s = "hello";
// 字符串转数组
char[] ch = s.toCharArray();
for (int i = 0; i < ch.length; i++) {
System.out.print(ch[i]);
}
System.out.println();
// 数组转字符串
String s2 = new String(ch);
System.out.println(s2);
1.3.3 格式化
String s = String.format("%d-%d-%d", 2019, 9,14);
System.out.println(s);//2019-9-14
1.4 字符串替换
String replaceAll(String regex, String replacement) 替换所有的指定内容String replaceFirst(String regex, String replacement) 替换第一个内容
String str = "helloworld" ;
System.out.println(str.replaceAll("l", "_"));//he__owor_d
System.out.println(str.replaceFirst("l", "_"));//he_loworld
1.5 字符串拆分
String[] split(String regex) 将字符串全部拆分String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit 组
String str = "hello world hello world" ;
String[] result = str.split(" ") ; // 按照空格拆分
for(String s: result) {
System.out.println(s);
}
//hello
//world
//hello
//world
String str = "hello world hello world" ;
String[] result = str.split(" ",3) ;
for(String s: result) {
System.out.println(s);
}
//hello
//world
//hello world
String str1 = "192.168.1.1" ;
String[] result1 = str1.split("\\.") ;
for(String s: result1) {
System.out.println(s);
}
String str = "hello*world*hello*world" ;
String[] result = str.split("\\*",3) ;
for(String s: result) {
System.out.println(s);
}
String str = "hello\\.world\\.hello\\.world" ;
String[] result = str.split("\\\\.",3) ;
for(String s: result) {
System.out.println(s);
}
//hello
//world
//hello\.world
1.6 字符串截取
1. 索引从0开始
2. 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标
String substring(int beginIndex) 从指定索引截取到结尾String substring(int beginIndex, int endIndex) 截取部分内容
String str = "helloworld" ;
System.out.println(str.substring(5));
System.out.println(str.substring(0, 5));
//world
//hello
1.7 其他操作方法
String.trim()去掉字符串中的左右空格 , 保留中间空格
String str = " [hello world] " ;
System.out.println("["+str。trim()+"]");
System.out.println(str.trim());
}
//[[hello world]]
//[hello world]
String toUpperCase() 字符串转大写String toLowerCase() 字符串转小写这两个函数只转换字母
String str = " heLLO123$%world asd " ;
System.out.println(str.toUpperCase());
System.out.println(str.toLowerCase())
//HELLO123$%WORLD ASD
//hello123$%world asd
1.8 字符串的不可变性
![](https://i-blog.csdnimg.cn/direct/1c5dc35f809c456e8923850d98667e9a.png)
String类中的字符实际保存在内部维护的value字符数组中,并且String类不可以被继承,value被final修饰,表示value不能修改,即不能引用其他字符数组,但是其引用空间中的内容可以修改。如下图:
final 修饰类表明该类不想被继承, final 修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内 容是可以修改的 。
PS:
为什么 String 要设计成不可变的?(不可变对象的好处是什么?)1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.2. 不可变对象是线程安全的.3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.
接上文:
1.9 字符串修改
public static void main(String[] args) {
String s = "hello";
s += " world";
System.out.println(s); // 输出:hello world
}
这种方式不推荐,因为中间创建了很多临时对象并且进行了StringBuild的append追加方法等。尽量避免对String的直接需要,如果要修改建议尽量使用StringBuffer或者StringBuilder来进行修改
1.9.1. StringBuilder和StringBuffer
由于 String 的不可更改特性,为了方便字符串的修改, Java 中又提供 StringBuilder 和 StringBuffer 类。这两个类大部分功能是相同的
StringBuff append(String str) 在尾部追加,相当于String的 += ,可以追加: boolean 、 char 、 char[] 、 double、 float 、 int 、 long 、 Object 、 String 、 StringBuff 的变量
StringBuffer S1 = new StringBuffer();
S1.append("Hello");
S1.append(" World");
System.out.println(S1);
StringBuffer S2 = new StringBuffer();
S2.append("Hello");
S2.append(" World");
System.out.println(S2==S1);
- char charAt(int index) 获取index位置的字符
- int length() 获取字符串的长度
- int capacity() 获取底层保存字符串空间总的大小
- void ensureCapacity(int mininmumCapacity) 扩容,
StringBuffer
的扩容方法通常在以下情况被自动调用,一般情况下不需要手动调用扩容方法
- void setCharAt(int index, char ch) 将index位置的字符设置为ch
- int indexOf(String str) 返回str第一次出现的位置
- int indexOf(String str, int fromIndex) 从fromIndex位置开始往后查找str第一次出现的位置
- int lastIndexOf(String str) 返回最后一次出现str的位置
- int lastIndexOf(String str, int fromIndex) 从fromIndex位置开始找str最后一次出现的位置
- StringBuff insert(int offset, String str) 在offset位置插入:八种基类类型 & String类型 & Object类型数据
- StringBuffer deleteCharAt(int index) 删除index位置字符
- StringBuffer delete(int start, int end) 删除[start, end)区间内的字符
- StringBuffer replace(int start, int end, String str) 将[start, end)位置的字符替换为str
- String substring(int start) 从start开始一直到末尾的字符以String的方式返回
- String substring(int start,int end) 将[start, end)范围内的字符以String的方式返回
- StringBuffer reverse() 反转字符串
- String toString() 将所有字符按照String的方式返回
StringBuffer s1 = new StringBuffer();
s1.append("Hello");
s1.append(" World");
System.out.println(s1);
StringBuffer s2 = new StringBuffer();
s2.append("Hello");
s2.append(" World");
System.out.println(s2==s1);
System.out.println(s1.charAt(0)); // 获取0号位上的字符 H
System.out.println(s1.length()); // 获取字符串的有效长度11
System.out.println(s1.capacity()); // 获取底层数组的总大小16
s1.setCharAt(0, 'h'); // 设置任意位置的字符 hello world
s1.insert(0, "Hello world!!!"); // Hello world!!!hello world
System.out.println(s1);
System.out.println(s1.indexOf("o")); // 获取o第一次出现的位置--4
System.out.println(s1.lastIndexOf("o")); // 获取o最后一次出现的位置--21
s1.deleteCharAt(0); // 删除首字符
s1.delete(0,5); // 删除[0, 5)范围内的字符
System.out.println(s1.lastIndexOf("hello", 20));//8
System.out.println(s1.lastIndexOf("h", 0));//-1
System.out.println(s1);
String str = s1.substring(0, 5); // 截取[0, 5)区间中的字符以String的方式返回
System.out.println(str);
s1.replace(0,5,"WORLD");//WORLD!!!hello World
System.out.println(s1);
String S1= s1.substring(0);//WORLD!!!hello World
System.out.println(S1);
String S4= s1.substring(0,7);
System.out.println(S4);//WORLD!!
s1.reverse(); // 字符串逆转
str = s1.toString(); // 将StringBuffer以String的方式返回
System.out.println(str);
String和StringBuilder类要想互相转换,可以采用如下原则:
1. String 变为 StringBuilder: 利用 StringBuilder 的构造方法或 append() 方法String str = "example"; StringBuilder builder = new StringBuilder(str);
String str = "Hello"; StringBuilder builder = new StringBuilder(); builder.append(str); System.out.println(builder);
2. StringBuilder 变为 String: 调用 toString() 方法StringBuilder sb = new StringBuilder("Hello"); sb.append(" World"); String str = sb.toString(); System.out.println(str);
1. String 、 StringBuffer 、 StringBuilder 的区别String 的内容不可修改, StringBuffer 与 StringBuilder 的内容可以修改 .StringBuffer 与 StringBuilder 大部分功能是相似的StringBuffer 采用同步处理,属于线程安全操作;而 StringBuilder 未采用同步处理,属于线程不安全操作