java.lang.String 类代表字符串。Java程序中所有的字符串文字(例如"abc" )都可以被看作是实现此类的实例。字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。
String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。
Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持(toString()方法)。
String的特点
- 字符串String类型本身是final声明的,意味着我们不能继承String。
- 字符串的对象也是不可变对象,意味着一旦进行修改,就会产生新对象。我们修改了字符串后,如果想要获得新的内容,必须重新接收。如果程序中涉及到大量的字符串的修改操作,那么此时的时空消耗比较高。可能需要考虑使用StringBuilder或StringBuffer的可变字符序列。
- String对象内部是用字符数组进行保存的。JDK1.9之前有一个char[ ] value数组,JDK1.9之后byte[ ]数组"abc"等效于char[] data={ 'a' , 'b' , 'c' }`。、
- String类中这个char[] values数组也是final修饰的,意味着这个数组不可变,然后它是private修饰,外部不能直接操作它,String类型提供的所有的方法都是用新对象来表示修改后内容的,所以保证了String对象的不可变。
- 字符串保存在常量池中
最常用的构造方法
代码示例
package demo01;
public class Demo {
public static void main(String[] args) {
// public String() : 创建一个空白字符串对象,不含有任何内容
String s1 = new String();
System.out.println(s1);
// public String(char[] chs) : 根据字符数组的内容,来创建字符串对象
char[] chs = {'a', 'b', 'c'};
String s2 = new String(chs);
System.out.println(s2);
// public String(String original) : 根据传入的字符串内容,来创建字符串对象
String s3 = new String("123");
System.out.println(s3);
// 直接赋值的方式创建字符串对象,内容就是abc
String s = "abc";
System.out.println(s);
}
}
构造方法创建字符串对象与直接赋值方式创建字符串对象的区别
通过构造方法创建:通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然字符串内容相同,但是地址值不同。
package demo01;
public class Demo {
public static void main(String[] args) {
char[] chs = {'a','b','c'};
String s1 = new String(chs);// s1字符串的内容: abc
String s2 = new String(chs);// s2字符串的内容: abc
// 上面的代码中,JVM首先会先创建一个字符数组,然后每一次new的时候都会有一个新的地址,只不过s1和s2参考的字符串内容是相同的
//比较内存地址值
System.out.println(s1==s2);//false
}
}
直接赋值方式创建:以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护
package demo01;
public class Demo {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
// 上面的代码中,针对第一行代码,JVM会建立一个String对象放在字符串池中,并给s1参考;
// 第二行代码,则让s2直接参考字符串池中String对象,也就是说他们本质上是同一个对象
//比较内存地址值
System.out.println(s1==s2);//true
}
}
字符串的对象的个数
字符串常量对象
String s1 = "hello";//1个,在常量池中
2、字符串的普通对象和常量对象一起
String s2 = new String("hello");//2个
//s2首先指向堆中的一个字符串对象,然后堆中字符串的value数组指向常量池中常量对象的value数组
拼接结果的存储和比较问题
- 常量+常量:结果是常量池。常量池的字符串对象可以共享
- 常量与变量 或 变量与变量:结果是堆
- 拼接后调用intern方法:结果在常量池
字符串的比较
方式一:使用== 对字符串进行比较
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2);//true
String str3 = new String("hello");
String str4 = new String("hello");
System.out.println(str1 == str4); //false
System.out.println(str3 == str4); //false
结论:
- 比较基本数据类型:比较的是具体的值
- 比较引用数据类型:比较的是对象地址值
方式二:使用方法
- public boolean equals(Object s) 比较两个字符串内容是否相同、区分大小写,因为String类型重写equals,只要两个字符串的字符内容相同,就会返回true
- public boolean equalsIgnoreCase (String anotherString) :将此字符串与指定对象进行比较,忽略大小写。
字符串的方法有很多,我们掌握常用的就行,其他的可以查询api
- boolean isEmpty( ):字符串是否为空
- int length( ):返回字符串的长度,也就是字符的个数
- String concat(xx):将指定的字符串连接到该字符串的末尾。
- boolean equals(Object obj):比较字符串是否相等,区分大小写
- boolean equalsIgnoreCase(Object obj):比较字符串是否相等,区分大小写
- int compareTo(String other):比较字符串大小,区分大小写,按照Unicode编码值比较大小
- int compareToIgnoreCase(String other):比较字符串大小,不区分大小写
- String toLowerCase():将字符串中大写字母转为小写
- String toUpperCase():将字符串中小写字母转为大写
- String trim():去掉字符串前后空白符
- boolean contains(xx):是否包含xx
- int indexOf(xx):从前往后找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1
- int lastIndexOf(xx):从后往前找当前字符串中xx,即如果有返回最后一次出现的下标,要是没有返回-1
- String substring(int beginIndex) :返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
- String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
- char charAt(index):返回[index]位置的字符
- char[ ] toCharArray( ): 将此字符串转换为一个新的字符数组返回
- String(char[ ] value):返回指定数组中表示该字符序列的 String。
- String(char[] value, int offset, int count):返回指定数组中表示该字符序列的 String。
- static String copyValueOf(char[] data): 返回指定数组中表示该字符序列的 String
- static String copyValueOf(char[] data, int offset, int count):返回指定数组中表示该字符序列的 String
- static String valueOf(char[] data, int offset, int count) : 返回指定数组中表示该字符序列的 String
- static String valueOf(char[] data) :返回指定数组中表示该字符序列的 String
- byte[ ] getBytes():编码,把字符串变为字节数组,按照平台默认的字符编码进行编码
- byte[ ] getBytes(字符编码方式):按照指定的编码方式进行编码
- new String(byte[] ) 或 new String(byte[], int, int):解码,按照平台默认的字符编码进行解码
- new String(byte[ ],字符编码方式 ) 或 new String(byte[], int, int,字符编码方式):解码,按照指定的编码方式进行解码
- boolean startsWith(xx):是否以xx开头
- boolean endsWith(xx):是否以xx结尾
- String replace(xx,xx):不支持正则
- String replaceFirst(正则,value):替换第一个匹配部分
- String repalceAll(正则, value):替换所有匹配部分
- String[ ] split(正则):按照某种规则进行拆分
部分方法,代码演示
// 创建字符串对象
String str = "hello-world!";
// 获取字符串的长度(字符串的字符个数)
int len = str.length();
System.out.println("str的字符串长度是:"+len);// 12
// str字符串末尾拼接上hello-itheima
String newStr = str.concat("hello-itheima");
System.out.println("拼接后的字符串:"+newStr);// hello-world!hello-itheima
// 获取str中索引为1的字符
char ch = str.charAt(1);
System.out.println("索引为1的字符:"+ch);// e
System.out.println("========================================================");
// 创建字符串对象
String str1 = "hello-world-hello-itheima-hello-java-hello-itcast";
// 查找hello第一次出现的索引位置
int index1 = str1.indexOf("hello");
System.out.println("hello第一次出现的索引位置:"+index1);// 0
// 查找hello第二次出现的索引位置
int index2 = str1.indexOf("hello", index1+1);
System.out.println("hello第二次出现的索引位置:"+index2);// 12
// 查找hello第三次出现的索引位置
int index3 = str1.indexOf("hello", index2+1);
System.out.println("hello第三次出现的索引位置:"+index3);// 26
System.out.println("========================================================");
// 查找hello最后一次出现的索引位置
int lastIndex1 = str1.lastIndexOf("hello");
System.out.println("hello最后一次出现的索引位置:"+lastIndex1);// 37
// 查找hello倒数第二次出现的索引位置
int lastIndex2 = str1.lastIndexOf("hello", lastIndex1 - 1);
System.out.println("hello倒数第二次出现的索引位置:"+lastIndex2);// 26
System.out.println("========================================================");
String str3 = "hello-world-hello-itheima";
// 获取world-hello-itheima子字符串
String subStr1 = str3.substring(6);
System.out.println("subStr1:"+subStr1);// world-hello-itheima
// 获取world-hello子字符串
String subStr2 = str3.substring(6, 17);
System.out.println("subStr2:"+subStr2);// world-hello
需求: 定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出反转后的字符串 例如,键盘录入 abc,输出结果 cba
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// 键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = sc.next();
// 调用reverse
System.out.println(reverse(str));
}
public static String reverse(String str){
// 功能:字符串反转
// 1.创建空白的字符串对象
String newStr = "";
// 2.倒叙遍历传入的字符串对象
for (int i = str.length()-1;i >= 0; i--) {
// 3.在循环中,获取遍历出来的字符
char c = str.charAt(i);
// 4.在循环中,拼接遍历出来的字符
newStr += c;
}
// 5.返回反转后的字符串
return newStr;
}
}
StringBuilder类
因为String对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低。因此,JDK又在java.lang包提供了可变字符序列StringBuilder和StringBuffer类型。StringBuffer:老的,线程安全的(因为它的方法有synchronized修饰)。StringBuilder:线程不安全的。 StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的内容是可变的。
常用的构造方法
代码示例
public class Test {
public static void main(String[] args) {
// 创建空白可变字符串对象 ""
StringBuilder sb1 = new StringBuilder();
System.out.println("sb1:"+sb1+"=");// sb1:=
System.out.println("sb1的长度:"+sb1.length());// 0
// 把不可变字符串转换为可变字符串
String str = "itheima";// 不可变的字符串
StringBuilder sb2 = new StringBuilder(str);// 可变的字符串,字符串内容是:itheima
System.out.println("sb2:"+sb2);// sb2:itheima
System.out.println("sb2的长度:"+sb2.length());// 7
}
}
常用方法
- public StringBuilder append(任意类型): 拼接数据,并返回对象本身
- public StringBuilder insert(int offset, 任意类型): 在指定位置插入数据,并返回对象本身
- public StringBuilder reverse( ) :反转字符串,并返回对象本身
代码示例
// 创建可变字符串对象
StringBuilder sb1 = new StringBuilder("hello");
// sb1字符串末尾拼接上"-world"
StringBuilder sb2 = sb1.append("-world");
System.out.println(sb1);// hello-world
System.out.println(sb2);// hello-world
System.out.println(sb1==sb2);// sb1和sb2的地址值是一样的,true
System.out.println("=======================================");
// 把-java插入到sb1可变字符串中,使得sb1为:hello-java-world
sb1.insert(5,"-java");
System.out.println(sb1);// hello-java-world
System.out.println("=======================================");
// 把sb1中的字符串内容进行反转
StringBuilder sb3 = sb1.reverse();
System.out.println(sb1);// dlrow-avaj-olleh
System.out.println(sb3);// dlrow-avaj-olleh
System.out.println(sb1==sb3);// true
StringBuilder和String相互转换
- String转换为StringBuilder:public StringBuilder(String s):通过StringBuilder的构造方法就可以实现把 String 转换为 StringBuilder
- StringBuilder转换为String:public String toString():通过StringBuilder类中的 toString() 就可以实现把 StringBuilder 转换为 String
示例代码
String str = "hello-world";
//String--->StringBuilder: public StringBuilder(String str)
StringBuilder sb = new StringBuilder(str);
//StringBuilder-->String : public String toString()
String s = sb.toString();
System.out.println(sb);// hello-world 可变字符串
System.out.println(s);// hello-world 不可变的字符串
需求
定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如,数组为int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
public class Test {
public static void main(String[] args) {
int[] arr = {1,2,3};
System.out.println(arrayToString(arr));
}
public static String arrayToString(int[] arr) {
// 1.创建可变的空白字符串对象
StringBuilder sb = new StringBuilder();
// 2.循环遍历传入的数组元素
for (int i = 0; i < arr.length; i++) {
// 3.在循环中,获取遍历出来的元素
int e = arr[i];
// 4.在循环中,判断该元素:
if (i == 0) {
// 5.如果遍历出来的元素是第一个元素,那么拼接的格式为: [ + 元素 + 逗号空格
sb.append("[").append(e).append(", ");
} else if (i == arr.length - 1) {
// 5.如果遍历出来的元素是最后一个元素,那么拼接的格式为: 元素 + ]
sb.append(e).append("]");
} else {
// 5.如果遍历出来的元素是中间元素,那么拼接的格式为: 元素 + 逗号空格
sb.append(e).append(", ");
}
}
// 6.返回字符串
return sb.toString();
}
}


