【Java|第十九篇】面向对象九——String类和枚举类
(四)面向对象
11、String类
(1)概述
<1>String是一个类,引用数据类型,用来表示字符串;
<2>String是Lang包下的类,使用不需要导包;
<3>字符串的值不能变,String对象是不可变的,一旦创建,他们的值就不能被修改。
这里的意思是String对象所标识的栈空间中的引用地址值可以改
但是堆空间中创建的对象的属性值不可以改变,一旦创建就不能更改!
示例:
String s1 = new String("123"); s1 = new String("345"); //这样修改是可以的,并没有改动上一个对象中的属性123,只是更改了s1的引用地址值 s1 = null; //这样修改也可以,将引用地址值指向了null
String类型的这个特点,使得很多操作其实都是在创建新的对象,并不是在原对象上操作
(2)String类的常用构造方法: 
下面给出一些案例:
public class Test_Basic {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);String s4 = "hello";System.out.println(s4);}
}
接下来是内存结构的展示:
(3)常量池:
创建字符串对象,和其他普通对象一样,会占用计算机的资源(时间和空间),作为最常用的数据类型,大量频繁的创建字符串对象,会极大程度地影响程序的性能。
JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化
String常量池:
在Java中,String常量池是一块特殊的内存区域,用于存储字符串常量。String常量池的设计目的是为了节省内存和提高性能。
当我们创建字符串常量时,如果字符串常量池中已经存在相同内容的字符串,那么新创建的字符串常量会直接引用已存在的字符串对象,而不会创建新的对象。这样可以避免重复创建相同内容的字符串,节省内存空间。
在JDK8及之后的版本中,字符串常量池的位置与其他对象的存储位置,都位于堆内存中。这样做的好处是,字符串常量池的大小可以根据需要进行调整,并且可以享受到垃圾回收器对堆内存的优化。
Java将字符串放入String常量池的方式:
1. 直接赋值:通过直接赋值方式创建的字符串常量会被放入常量池中。
例如: String str = "Hello";
2. 调用String类提供intern()方法:可以将字符串对象放入常量池中,并返回常量池中的引用。
例如: String str = new String("World").intern();
注意:通过new关键字创建的字符串对象不会放 入常量池中,而是在堆内存中创建一个新的对象。只有通过直接赋值或调用intern()方法才能将字符串放入常量池中。
案例:
public class Test062_String {public static void main(String[] args) {String s1 = "Hello"; // 字符串常量,放入常量池String s2 = "Hello"; // 直接引用常量池中的字符串对象System.out.println(s1 == s2); // true,引用相同// 直接new String对象,不会将'World'放入常量池String s3 = new String("World");// 调用intern()方法,将'World'放入常量池,并返回常量池中的引用String s4 = new java.lang.String("World").intern();String s5 = "World";System.out.println(s3 == s4); // false,引用不同System.out.println(s4 == s5); // true,引用相同}
}
public class Test062_String2 {public static void main(String[] args) {String s1 = "a";String s2 = "b";// 常量优化机制:"a" 和 "b"都是字面值常量,借助 + 连接,其结果 "ab" 也被当作常量String s3 = "a" + "b";String s4 = "ab";System.out.println(s3.equals(s4)); // trueSystem.out.println(s3 == s4); // trueSystem.out.println("-------------");String s5 = s1 + s2;System.out.println(s4.equals(s5)); // trueSystem.out.println(s4 == s5); // falseSystem.out.println("-------------");String s6 = (s1 + s2).intern();System.out.println(s4.equals(s6)); // trueSystem.out.println(s4 == s6); // true}
}
使用 + 拼接多个字符串常量,拼接的结果仍旧是字符串常量 ,变量不可以如果结果字符串常量在常量池中不存在,则Java会将其放入到字符串常量池中
(4)常用方法:
1.
public int length()
用法:获取字符串的长度(字符个数)
返回值:
int
类型,即字符串中字符的数量调用者:
String
对象本身(如"abc".length()
)是否改变原对象:不改变。仅查询长度,不修改字符串内容
示例:
String s = "hello"; int len = s.length(); // len = 5('h','e','l','l','o'共5个字符)
2.
public boolean equals(Object anObject)
用法:比较当前字符串与参数对象的内容是否完全相同(严格区分大小写)
返回值:
boolean
类型。true
表示内容完全相同,false
表示不同调用者:
String
对象本身(如s1.equals(s2)
)是否改变原对象:不改变。仅做比较操作,不修改任何字符串
注意:
需与
==
区分:equals()
比较内容,==
比较对象地址若参数为
null
,返回false
示例:
String s1 = "abc"; String s2 = "ABC"; boolean b1 = s1.equals("abc"); // true(内容相同) boolean b2 = s1.equals(s2); // false(大小写不同)
3.
public char charAt(int index)
用法:获取字符串中指定索引位置的字符(索引从 0 开始)
返回值:
char
类型,即索引位置对应的字符调用者:
String
对象本身(如s.charAt(2)
)是否改变原对象:不改变。仅查询指定位置的字符
注意:若索引超出范围(
index < 0
或index >= length()
),会抛出StringIndexOutOfBoundsException
示例:
String s = "hello"; char c = s.charAt(1); // c = 'e'(索引1对应的字符)
4.
public char[] toCharArray()
用法:将字符串转换为字符数组(每个元素对应字符串中的一个字符)
返回值:
char[]
类型,即包含字符串所有字符的数组调用者:
String
对象本身(如s.toCharArray()
)是否改变原对象:不改变。仅生成新的字符数组,原字符串不变
示例:
String s = "abc"; char[] arr = s.toCharArray(); // arr = {'a','b','c'}
5.
public String[] split(String regex)
用法:根据传入的正则表达式
regex
切割字符串,返回切割后的子字符串数组返回值:
String[]
类型,即切割后的子字符串集合调用者:
String
对象本身(如s.split(",")
)是否改变原对象:不改变。仅根据规则切割并生成新数组,原字符串不变
注意:
regex
是正则表达式(如"\\."
表示按点切割,需转义)若切割后无内容,可能返回空数组或包含空字符串
示例:
String s = "a,b,c"; String[] parts = s.split(","); // parts = {"a","b","c"}
6.
public String substring(int begin, int end)
用法:截取字符串中从
begin
索引(包含)到end
索引(不包含)的子字符串,即范围[begin, end)
返回值:
String
类型,即截取得到的新字符串调用者:
String
对象本身(如s.substring(1,3)
)是否改变原对象:不改变。生成新的子字符串,原字符串不变
注意:若
begin
或end
超出范围,会抛出StringIndexOutOfBoundsException
示例:
String s = "hello"; String sub = s.substring(1,4); // sub = "ell"(索引1到3的字符:'e','l','l')
7.
public String substring(int begin)
用法:从
begin
索引(包含)开始截取字符串,直到字符串末尾,即范围[begin, length())
返回值:
String
类型,即截取得到的新字符串调用者:
String
对象本身(如s.substring(2)
)是否改变原对象:不改变。生成新的子字符串,原字符串不变
示例:
String s = "hello"; String sub = s.substring(2); // sub = "llo"(从索引2到末尾的字符)
8.
public String replace(CharSequence target, CharSequence replacement)
用法:将字符串中所有与
target
匹配的子序列,替换为replacement
返回值:
String
类型,即替换后的新字符串调用者:
String
对象本身(如s.replace("a","b")
)是否改变原对象:不改变。生成替换后的新字符串,原字符串不变
注意:替换所有匹配项(非首次匹配)