String类介绍
概述
java.lang.String类代表字符串。Java程序中所有的字符串文字(例如"abc" )都可以被看作是实现此类的实例。字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。String 类在 java.lang 包下,所以使用的时候不需要导包!
字符串的特点
- 字符串String类型本身是final声明的,意味着我们不能继承String。
- 字符串的对象也是不可变对象,意味着一旦进行修改,就会产生新对象。我们修改了字符串后,如果想要获得新的内容,必须重新接收。如果程序中涉及到大量的字符串的修改操作,那么此时的时空消耗比较高。可能需要考虑使用StringBuilder或StringBuffer的可变字符序列。
- String对象内部是用字符数组进行保存的。JDK1.9之前有一个char[ ] value数组,JDK1.9之后byte[ ]数组。例如:"abc"等效于 char[] data={ 'a' , 'b' , 'c' }
- 就因为字符串对象设计为不可变,那么所以字符串有常量池来保存很多常量对象。常量池中的对象是可以共享使用的
字符串的构造方法
- public String( ) :初始化新创建的 String对象,以使其表示空字符序列。
- public String(String original): 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
- public String(char[] value) :通过当前参数中的字符数组来构造新的String。
- public String(char[] value,int offset, int count) :通过字符数组的一部分来构造新的String。
- public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String。
- public String(byte[] bytes, int offset, int length):根据指定字节数组范围的内容,来创建字符串对象
代码示例
public class Demo01String {
public static void main(String[] args) {
//public String() :初始化新创建的 String对象,以使其表示空字符序列。
String str1 = new String();
System.out.println("-" + str1 + "-");// --
//String(String original): 新创建的字符串是该参数字符串的副本。
String str2 = new String("abc");
System.out.println(str2);//abc
//String(char[] value) :通过当前参数中的字符数组来构造新的String。
char[] c1 = {'a', 'b', 'c', 'd', 'e'};
String str3 = new String(c1);
System.out.println(str3);//abcde
// String(char[] value,int offset, int count) :通过字符数组的一部分来构造新的String。
String str4 = new String(c1, 0, 3);
System.out.println(str4);//abc
//String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String。
// 根据字节数组的内容,来创建字符串对象
byte[] bys = {97, 98, 99, 100, 101, 102};
String str5 = new String(bys);// str4字符串内容:"abcdef"
System.out.println(str5);// abcdef
// 根据指定字节数组范围的内容,来创建字符串对象
String str6 = new String(bys, 2, 3);// str5字符串内容:"cde"
System.out.println(str6);// cde
// 直接赋值的方式创建字符串对象
String str7 = "abc";// str6字符串内容:"abc"
System.out.println(str7); //abc
}
}
创建字符串对象两种方式的区别
- 通过构造方法创建:通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然字符串内容相同,但是地址值不同
- 直接赋值方式创建:以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护
什么情况下字符串对象在常量池?
- 常量+常量:结果是常量池
- 常量与变量 或 变量与变量:结果是堆
- 拼接后调用intern方法:结果在常量池
- concat方法拼接,哪怕是两个常量对象拼接,结果也是在堆
字符串常用方法
字符串的比较
方式一:使用 == 进行比较
- 如果是基本数据类型,比较的是数值
- 如果是引用数据类型,比较的是地址值
int a = 1;
int b = 1;
// 如果是基本数据类型,比较的是数值
System.out.println(a == b);//true
String s = "abc";
String s1 = "abc";
String s2 = new String("abc");
//比较s和s1对象的地址值
System.out.println(s == s1);//true
//比较s和s2对象的地址值
System.out.println(s == s2); //false
方式二:使用字符串对象提供的方法
- public boolean equals(Object s) 比较两个字符串内容是否相同、区分大小写
- public boolean equalsIgnoreCase (String anotherString) :将此字符串与指定对象进行比较,忽略大小写。
String str1 = "hello";
String str2 = "hello";
//只要两个字符串的字符内容相同,就会返回true
System.out.println(str1.equals(str2));//true
//equalsIgnoreCase:比较的是对象的内容,不区分大小写
String str3 = "Hello";
System.out.println(str1.equals(str3));//false
System.out.println(str1.equalsIgnoreCase(str3));//true
常用方法
- public int length () :返回此字符串的长度。
String str = "abc123456789";
// 获取字符串的长度(字符串的字符个数)
int length = str.length();
System.out.println(str.length());// 12
- public String concat (String str) :将指定的字符串连接到该字符串的末尾。拼接
String str = "abc";
// str字符串末尾拼接上字符串你好
String newStr = str.concat("你好");
System.out.println(str);// abc
System.out.println(newStr); //abc你好
- public char charAt (int index) :返回指定索引处的 char值。
String str = "abc";
char ch = str.charAt(1);
System.out.println("索引为1的字符:"+ch);// b
- public int indexOf (String str) :返回指定子字符串第一次出现在该字符串内的索引。默认情况从第一个字符开始查找
- public int indexOf(String str, int fromIndex) : 返回从指定索引位置查找,该子字符串第一次出现在该字符串内的索引。
// 创建字符串对象
String str1 = "hello-world-hello-it-hello-java-hello-it";
// 查找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
- public int lastIndexOf(String str): 返回指定子字符串最后一次出现在该字符串内的索引。
- public int lastIndexOf(String str, int fromIndex): 返回从指定索引位置查找,,该子字符串最后一次出现在该字符串内的索引。
// 创建字符串对象
String str1 = "hello-world-hello-it-hello-java-hello-it";
// 查找hello最后一次出现的索引位置
int lastIndex1 = str1.lastIndexOf("hello");
System.out.println("hello最后一次出现的索引位置:"+lastIndex1);// 32
// 查找hello倒数第二次出现的索引位置
int lastIndex2 = str1.lastIndexOf("hello", lastIndex1 - 1);
System.out.println("hello倒数第二次出现的索引位置:"+lastIndex2);// 21
- public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。
- public String substring (int beginIndex, int endIndex) :返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndex。
// 创建字符串对象
String str3 = "hello-world";
// 获取world子字符串
String subStr1 = str3.substring(6);
System.out.println("subStr1:" + subStr1);// subStr1: world
// 获取hello子字符串
String subStr2 = str3.substring(0, 5);
System.out.println("subStr2:" + subStr2);// subStr2:hello
- public boolean isEmpty( ); 判断字符串是否为空
String str1 = "";// 空字符串
String str2 = "a";// 非空字符串
System.out.println(str1.isEmpty());// true
System.out.println(str2.isEmpty());// false
- public boolean contains(CharSequence s); 判断字符串中是否包含 给定的字符串。
String str = "hello-world-hello-it";
// 判断str字符串是否包含指定的子字符串
System.out.println(str.contains("it"));// true
System.out.println(str.contains("good"));// false
- public boolean endsWith(String s):判断字符串是否以 给定的字符串 结尾。
- public boolean startsWith(String s):判断字符串是否以 给定的字符串 开头。
String str = "hello-world-hello-it";
// 判断str字符串是否以hel开头
System.out.println(str.startsWith("hel"));// true
// 判断str字符串是否以hea开头
System.out.println(str.startsWith("hea"));// false
// 判断str3字符串是否以it结尾
System.out.println(str.endsWith("it"));// true
// 判断str3字符串是否以it1结尾
System.out.println(str.endsWith("it1"));// false
- public String replace(CharSequence oldStr,CharSequence newStr):用新内容替代旧内容,返回新的字符串
// 创建字符串对象
String str = "hello-world-hello";
// 把hello替换为good
String replaceStr = str.replace("hello", "good");
System.out.println("替换后的字符串内容:"+replaceStr);// 替换后的字符串内容:good-world-good
System.out.println("替换前的字符串内容:"+str);// 替换前的字符串内容:hello-world-hello
- public String toLowerCase():把字母都转成其对应的小写形式。
- public String toUpperCase():把字母都转成其对应的大写形式。
// 创建字符串对象
String str = "hello-world-hello";
// 把str1中的字母全部转换为大写字母
String s1 = str.toUpperCase();
System.out.println(s1);// HELLO-WORLD-HELLO
// 把str1中的字母全部转换为大写字母
String s2 = str.toLowerCase();
System.out.println(s2);// hello-world-hello
- public Char[ ] toCharArray():把字符串转换为数组
- public byte[ ] getBytes( ) :把字符串转换为字节数组
// 创建字符串对象
String str = "hello-world-hello";
// 把str字符串转换为字符数组
char[] arr1 = str.toCharArray();
// 把str字符串转换为字节数组
byte[] arr2 = str.getBytes();
- public String trim( ):移除首尾空格。
// 移除首尾空格
String username = " admin ";
String trimStr = username.trim();
System.out.println("="+trimStr+"="); // =admin=
- public String[ ] split(String regex):根据给定的内容,切割字符串,返回字符串数组。参数regex: 分割的规则(普通的字符串,也可以是特殊的字符串(正则表达式))
// 创建字符串对象
String str = "hello .world .hello";
// 以.对str3进行分割
String[] arr = str.split("\\.");// .特殊字符串(正则表达式),而在正则表达式中点表示任意字符
System.out.println(Arrays.toString(arr)); //[hello , world , hello]
StringBuilder类
由来:
- 由于String类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象。 在API中对String类有这样的描述:字符串是常量,它们的值在创建后不能被更改。由此可知,如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。为了解决这一问题,可以使用java.lang.StringBuilder类。
StringBuilder类概述
- StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的内容是可变的。StringBuilder 拼接是直接在本身的字符串末尾进行拼接的。StringBuilder、StringBuffer的API是完全一致的。StringBuffer:老的,线程安全的(因为它的方法有synchronized修饰)StringBuilder:线程不安全的。
常用的构造方法
代码示例
// public StringBuilder() 创建一个空白可变字符串对象,不含有任何内容
StringBuilder sb1 = new StringBuilder();
System.out.println("sb1:"+sb1+"=");// sb1:=
System.out.println("sb1的长度:"+sb1.length());// 0
//public StringBuilder(String str) 把不可变字符串转换为可变字符串
String str = "it";// 不可变的字符串
StringBuilder sb2 = new StringBuilder(str);// 可变的字符串,字符串内容是:it
System.out.println("sb2:"+sb2);// sb2:it
System.out.println("sb2的长度:"+sb2.length());// 2
常用方法
- public StringBuilder append(任意类型): 拼接数据,并返回对象本身
- public StringBuilder insert(int offset, 任意类型) :在指定位置插入数据,并返回对象本身
- public StringBuilder reverse( ) : 反转字符串,并返回对象本身
StringBuilder和String相互转换
- String转换为StringBuilder:public StringBuilder(String s):通过StringBuilder的构造方法就可以实现把 String 转换为 StringBuilder
- StringBuilder转换为String:public String toString():通过StringBuilder类中的 toString() 就可以实现把 StringBuilder 转换为 String
部分方法,代码示例
- 需求:定义一个方法,把 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();
}
}
- 需求:定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果 例如,键盘录入abc,输出结果 cba
public class Test {
public static void main(String[] args) {
// 键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = sc.next();
// 反转
System.out.println(reverse(str));
}
public static String reverse(String str){
//连锁式编程
return new StringBuilder(str).reverse().toString();
}
}
其他方法有很多,例如:
- public StringBuffer delete(int start, int end):删除[start,end)之间字符
- public StringBuffer deleteCharAt(int index):删除[index]位置字符
- public void setCharAt(int index, xx):替换[index]位置字符
- public void setLength(int newLength) :设置当前字符序列长度为newLength
- public StringBuffer replace(int start, int end, String str):替换[start,end)范围的字符序列为str
- public int indexOf(String str):在当前字符序列中查询str的第一次出现下标
- public int indexOf(String str, int fromIndex):在当前字符序列[fromIndex,最后]中查询str的第一次出现下标
- public int lastIndexOf(String str):在当前字符序列中查询str的最后一次出现下标
- public int lastIndexOf(String str, int fromIndex):在当前字符序列[fromIndex,最后]中查询str的最后一次出现下标
- public String substring(int start):截取当前字符序列[start,最后]
- public String substring(int start, int end):截取当前字符序列[start,end)
- public String toString():返回此序列中数据的字符串表示形式
我们可以根据实际需要,去API中查询使用