Ⅰ. 常用方法
一、构造方法
public static void main(String[] args) {
*// 1. 常量字符串构造(推荐!!!)*
* *String s1 = "abc";
System.*out*.println(s1);
*// 2. 使用new构造对象(不推荐!!!)*
* *String s2 = new String("abc");
System.*out*.println(s2);
*// 3. 使用字节数组构造(还是会转变成字符处理)*
* *byte[] arr = new byte[]{ 97, 98, 99 };
String s3 = new String(arr);
System.*out*.println(s3);
}☘注意事项:
String是引用类型 ,底层并不存储字符串本身!

-
对于上面第一种构造方式来说,实际上是对常量池 中
"abc"的一个引用,如果此时再创建一个String s2 = "abc",此时并不会真的又去开辟一段空间,而是让s2指向常量池中的"abc",减少内存开销,所以在使用s1==s2的时候虽然结果是true看起来是对的,但实际上比较的仍然是一个相同的地址,而不是比较字符串内容! -
接上一点,
String s1 = new String("abc")是在堆区开辟空间,而String s2 = "abc"是引用一个常量池中的空间,是不一样的! -
在
Java中""引起来的也是String类型对象。 -
String对象不能使用中括号访问某个字符 ,如s[0]是不允许的!
二、常用方法
-
判断字符串是否为空
-
boolean ``isEmpty``():检查字符串是否为空(即长度为0) -
boolean ``isBlank``():方法用于检查字符串是否为空白字符串(即字符串为空或仅包含空白字符)
-
-
对象比较
-
==:对于内置类型,比较的是变量中的值;对于引用类型,比较的是引用中的地址 -
boolean ``equals``(Object anObject):按照字典序比较是否相同 -
int ``compareTo``(String s):按照字典序进行比较大小,返回差值 -
boolean ``equalsIgnoreCase``(String str):与equals相同,但是忽略大小写比较 -
int ``compareToIgnoreCase``(String str):与compareTo相同,但是忽略大小写比较
-
-
字符串查找
-
char ``charAt``(int index):返回index下标处字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常 -
int ``indexOf``(int ch):返回ch第一次出现的位置,没有返回-1 -
int ``lastIndexOf``(int ch):从后往前找,返回ch第一次出现的位置,没有返回-1 -
上面这些方法都有重载从哪个位置开始寻找的版本!
-
-
转化
-
字符串和数值转化:
-
对象转化为字符串:
String.``valueOf``(xxx) -
字符串转化为指定对象:如
Integer.``parseInt``(xxx)、Double.``parseDouble``(xxx)等等
-
-
大小写转化:
-
转成大写:
String ``toUpperCase``() -
转成小写:
String ``toLowerCase``()
-
-
字符串和数组转化:
-
字符串转数组:
char[] ``toCharArray``() -
数组转字符串:构造用数组构造一个字符串对象即可
String str = new String(arr);
-
-
字符串格式化:
String s = String.``format``("%d-%d-%d", 2019, 9,14);
-
-
字符串替换
-
String ``replace``(char oldChar, char newChar) -
当然有对应的其它方法如
replaceFirst、replaceAll以及重载版本,可以替换对应字符串而不只是字符! -
注意:由于字符串是不可变对象,替换不修改当前字符串,而是产生一个新的字符串 。
-
-
字符串拆分
-
String[] ``split``(String regex) -
String[] ``split``(String regex, int limit):将字符串以指定的格式,拆分为limit组 -
注意事项:
-
字符
|,*,+都是功能字符,所以得加上转义字符,即在前面加上\\。 -
如果是要表示字符
\,那么就得写成\\\\。 -
如果一个字符串中有多个分隔符,可以用
|作为连字符,如下面代码所示:
-
public static void main(String[] args) { String s = "lianwi&Nkqnwl%oino123)asd|kk"; String[] ret = s.split("&|%|\\)|\\|"); *// 让&、%、)、|作为分隔符,彼此之间用|连接起来!* * *System.*out*.println(Arrays.*toString*(ret)); } // 结果: [lianwi, Nkqnwl, oino123, asd, kk] -
-
字符串截取
-
String ``substring``(int beginIndex):从指定索引截取到结尾 -
String ``substring``(int beginIndex, int endIndex):截取部分内容 -
注意区间是左闭右开 的!
-
-
去掉字符串首尾空格
String ``trim``():去掉字符串中的左右空白(注意不只是空格)
-
将字符串放入字符串常量池中
public String ``intern``(),这个方法是用于一些大型项目需要减少内存的开销,将大量重复的字符串放入到常量池等等池中进行维护。如下面代码所示:
String s1 = new String("hello"); String s2 = "hello"; // 引用常量池中的对象 System.out.println(s1 == s2); // false(s1是堆对象) System.out.println(s1.intern() == s2); // true(s1.intern()返回常量池中的引用)
三、字符串的不变性
String 是一种不可变对象。字符串中的内容是不可改变 ,如果有修改的需求,只能通过创建一个新的对象来引用新的字符串,而不能在原来的字符串上进行修改 !

如上图所示,value 字符数组被 final 修饰,所以不能引用其它的字符数组,不过它是可以修改字符数组的内容的;但由于它又被 private 修饰,并且类内没有提供设置字符数组内容的接口,所以整体下来就达到了不能修改引用、不能修改内容的效果!
注意比如说 String s = "abc"不能修改指的是 "abc"不能修改,而不是说 s不能修改 ,s 是可以引用其它字符串的!
为什么
String要设计成不可变的? (不可变对象的好处是什么?)
方便实现字符串常量池 。如果
String可变,那么对象池就需要考虑写时拷贝的问题,因为一个字符串有多个对象引用。不可变对象是线程安全 的。
不可变对象更方便缓存
hashcode,作为key时可以更高效的保存到HashMap中。
Ⅱ. StringBuilder
StringBuilder 其实就相当于 C++ 中的 std::string,而 String 就相当于是 C++ 中的字符串常量。
也就是说 StringBuilder 的增删改都是在原来的字符串(更准确来说是字符数组)进行修改,而不像 String 一样是通过创建新的字符串,大大减少了增删改的开销!
| 方法 | 说明 |
|---|---|
StringBuff ``append``(String str) |
在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量 |
char ``charAt``(int index) |
获取 index 位置的字符 |
int ``length``() |
获取字符串的长度 |
int ``capacity``() |
获取底层保存字符串空间总的大小 |
void ``ensureCapacity``(int mininmumCapacity) |
扩容 |
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 的方式返回 |
注意:String 和 StringBuilder 不能直接转换。如果要想互相转换,可以采用如下原则:
-
String-->StringBuilder: 利用StringBuilder的构造方法或append()方法 -
StringBuilder-->String: 调用toString()方法。
package StringLearning;
*/***
* * 测试一下String和StringBuilder的速度*
* */*
public class demo {
public static void main(String[] args) {
String s1 = "";
StringBuilder s2 = new StringBuilder();
long start1 = System.*currentTimeMillis*();
for (int i = 0; i < 100000; i++) {
s1 += i;
}
long end1 = System.*currentTimeMillis*();
long start2 = System.*currentTimeMillis*();
for (int i = 0; i < 100000; i++) {
s2.append(i);
}
long end2 = System.*currentTimeMillis*();
System.*out*.println("String: " + (end1 - start1) + "ms");
System.*out*.println("StringBuilder: " + (end2 - start2) + "ms");
}
}
// 结果
String: 2391ms
StringBuilder: 1msⅢ. StringBuilder 与 StringBuffer 的区别
| 特性 | StringBuilder | StringBuffer |
|---|---|---|
| 线程安全 | ❌ 不安全 | ✅ 线程安全(内部方法加了 synchronized) |
| 适合场景 | 单线程环境下的字符串拼接 | 多线程环境下安全地修改字符串 |
| 性能表现 | 🚀 更快 | 🐢 稍慢 |
| 引入版本 | Java 5 | Java 1.0 |
| 使用方式 | 相同(API 几乎一模一样) | 相同 |