Java String类用法详解
在 java 中,String 是我们实际开发中使用频率很高的类,Java 通过 String 类来创建和操作字符串数据。
本节就为大家详细讲解 String 类。
String 类有一个带参数的构造函数:
下面的实例程序演示了两种方式的具体操作。
两种实例化方式有什么不同呢?哪种方式更优呢?我们先来看下面的代码:
这是因为第一种直接赋值的方式如“String str1 = "Hello"”,会首先在栈内存中开辟一块空间来保存变量 str1,同时在堆内存中开辟一块合适的空间来存储“Hello”,然后将堆内存的地址赋给栈内存中的 str1,即 str1 中存储的是“Hello”的内存地址。Java 同时在堆内存中提供了一个字符串常量池,专门用来存储 String 类型的对象。
此外字符串常量池有一个特点,在实例化一个 String 对象时,首先会在字符串常量池中查找,如果该字符串已经在池中创建,则直接返回它的内存地址。如果字符串常量池中不存在该字符串,就先创建再返回,即字符串常量池中不会创建值相等的重复字符串对象,str1 和 str2 的创建如下图所示。
所以 str1 == str2 的返回值是 true,但是字符串常量池只适用于直接赋值的方式。如果是通过构造函数创建的对象则完全不同,这种方式创建的对象会在堆内存中开辟对应的空间来存储。即通过 new String("World") 和 new String("World") 创建了两个对象,虽然值相等,但是会开辟两块内存来存储,所以内存地址肯定是不同的,str3 和 str4 的创建如下图所示。
所以 str3 == str4 的返回值为 false,我们在了解了 String 类使用构造函数创建实例化对象的内存模型之后,当判断两个字符串对象是否相同时,就可以直接使用 == 进行判断了。因为 == 可以比较内存地址,两个字符串的值无论是否相等,其内存地址肯定不同。
那么我们要如何来判断两个字符串对象的值是否相等呢?
String 类对继承自 Object 类的 equals() 方法进行了重写,在判断两个字符串对象是否相同时,equals() 会直接将字符串转为 byte 类型的数组,然后依次判断数组中的每一个值是否相等。如果全部相等,则认为两个字符串相等,返回 true,否则返回 false,表示两个字符串不相同。我们在判断两个字符串对象的值是否相等时,直接调用 String 的 equals() 方法即可。
实际上 String 类在存储字符串时,会将字符串的值保存在 byte 类型的数组中,我们知道数组一旦创建,其长度就是不可改变的。既然长度不可改变,也就意味着 byte 类型所存储的字符串值不可修改。一旦修改,就会重新创建一个 String 对象,用新对象的 byte 数组来存储修改之后的字符串。即如果我们修改了 String 对象的值,它就已经不是之前的对象了,而是一个新的对象,实例代码如下:
例如:
本节就为大家详细讲解 String 类。
String实例化
String 类对象的实例化方式有两种,第 1 种是直接赋值的方式,第 2 种是通过构造函数创建实例化对象的方式。String 类有一个带参数的构造函数:
public String(String original)将 String 对象的值直接传入即可创建。
下面的实例程序演示了两种方式的具体操作。
public class StringTest { public static void main(String[] args) { //第一种方式直接赋值 String str1 = "Hello"; //第二种方式通过构造函数 String str2 = new String("World"); System.out.println(str1); System.out.println(str2); } }运行结果为:
Hello
World
两种实例化方式有什么不同呢?哪种方式更优呢?我们先来看下面的代码:
public class StringTest { public static void main(String[] args) { String str1 = "Hello"; String str2 = "Hello"; System.out.println(str1 == str2); String str3 = new String("World"); String str4 = new String("World"); System.out.println(str3 == str4); } }上述代码非常简单,用直接赋值的方式创建了 String 对象 str1 和 str2,并且值相等。又用构造函数的方式创建了 String 对象 str3 和 str4,同样值相等。然后用 == 分别判断 str1 和 str2 是否相等,以及 str3 和 str4 是否相等。
运行结果为:== 判断的并不是对象的值是否相等,而是判断对象所引用的内存地址是否相等。
true
false
这是因为第一种直接赋值的方式如“String str1 = "Hello"”,会首先在栈内存中开辟一块空间来保存变量 str1,同时在堆内存中开辟一块合适的空间来存储“Hello”,然后将堆内存的地址赋给栈内存中的 str1,即 str1 中存储的是“Hello”的内存地址。Java 同时在堆内存中提供了一个字符串常量池,专门用来存储 String 类型的对象。
此外字符串常量池有一个特点,在实例化一个 String 对象时,首先会在字符串常量池中查找,如果该字符串已经在池中创建,则直接返回它的内存地址。如果字符串常量池中不存在该字符串,就先创建再返回,即字符串常量池中不会创建值相等的重复字符串对象,str1 和 str2 的创建如下图所示。
所以 str1 == str2 的返回值是 true,但是字符串常量池只适用于直接赋值的方式。如果是通过构造函数创建的对象则完全不同,这种方式创建的对象会在堆内存中开辟对应的空间来存储。即通过 new String("World") 和 new String("World") 创建了两个对象,虽然值相等,但是会开辟两块内存来存储,所以内存地址肯定是不同的,str3 和 str4 的创建如下图所示。
所以 str3 == str4 的返回值为 false,我们在了解了 String 类使用构造函数创建实例化对象的内存模型之后,当判断两个字符串对象是否相同时,就可以直接使用 == 进行判断了。因为 == 可以比较内存地址,两个字符串的值无论是否相等,其内存地址肯定不同。
那么我们要如何来判断两个字符串对象的值是否相等呢?
String 类对继承自 Object 类的 equals() 方法进行了重写,在判断两个字符串对象是否相同时,equals() 会直接将字符串转为 byte 类型的数组,然后依次判断数组中的每一个值是否相等。如果全部相等,则认为两个字符串相等,返回 true,否则返回 false,表示两个字符串不相同。我们在判断两个字符串对象的值是否相等时,直接调用 String 的 equals() 方法即可。
实际上 String 类在存储字符串时,会将字符串的值保存在 byte 类型的数组中,我们知道数组一旦创建,其长度就是不可改变的。既然长度不可改变,也就意味着 byte 类型所存储的字符串值不可修改。一旦修改,就会重新创建一个 String 对象,用新对象的 byte 数组来存储修改之后的字符串。即如果我们修改了 String 对象的值,它就已经不是之前的对象了,而是一个新的对象,实例代码如下:
public class StringTest { public static void main(String[] args) { String str1 = new String("Hello"); String str2 = str1; System.out.println(str2 == str1); str1 += " World"; System.out.println(str2 == str1); } }运行结果为:
true
false
String常用方法
String 类提供了大量的方法,在实际开发中使用这些方法可以很方便地完成对字符串的操作,常用方法如下表所示。方 法 | 描 述 |
---|---|
public String() | 创建一个值为空的对象 |
public String(String original) | 创建一个值为 original 的对象 |
public String(char value[]) | 将一个 char 型数组转为字符串对象 |
public String(char valued, int offset, int count) | 将一个指定范围的 chars 数组转为字符串对象 |
public String(byte[] bytes) | 将一个 byte 型数组转为字符串对象 |
public String(byte bytes[], int offset, int length) | 将一个指定范围的 byte 型数组转为字符串对象 |
public int length() | 返回字符串的长度 |
public boolean isEmpty() | 判断字符串是否为空 |
public char charAt(int index) | 返回字符串中指定位置的字符 |
public byte[] getBytes() | 将字符串转为 byte 型数组 |
public boolean equals(Object anObject) | 判断两个字符串是否相等 |
public boolean equalslgnoreCase(String anotherString) | 判断两个字符串是否相等并且忽賂大小写 |
public int compareTo(String anotherString) | 对两个字符串进行排序 |
public boolean startsWith(String prefix) | 判断是否以指定的值开头 |
public boolean endsWith(String suffix) | 判断是否以指定的值结尾 |
public int hashCode() | 获取字符串的散列值 |
public int indexOf(String str) | 从头开始查找指定字符的位置 |
public int indexOf(String str, int fromlndex) | 从指定的位置开始查找指定字符的位置 |
public String substring(int beginlndex) | 截取字符串从指定位置开始到结尾 |
public String substring(int beginlndex, int endindex) | 裁取字符串从指定位置开始到指定位置结束 |
public String concat(String str) | 追加字符串 |
public String replaceAll(String regex, String replacement) | 替换字符串 |
public String[] split(String regex) | 用指定字符串对目标字符串进行分割,返回数组 |
public String toLowerCase() | 将字符串转为小写 |
public String toUpperCase() | 将字符串转为大写 |
public char[] toCharArray() | 将字符串转为 char 型数组 |
例如:
public class StringTest { public static void main(String[] args) { char[] array = {'J','a','v','a',',','H','e','l','l','o',',','W','o','r','l','d'}; String str = new String(array); System.out.println(str); System.out.println("str长度:"+str.length()); System.out.println("str是否为空:"+str.isEmpty()); System.out.println("下标为2的字符是:"+str.charAt(2)); System.out.println("H的下标是:"+str.indexOf('H')); String str2 = "Hello"; System.out.println("str和str2是否相等:"+str.equals(str2)); String str3 = "HELLO"; System.out.println("str2和str3忽略大小写是否相等:"+str2.equalsIgnoreCase(str3)); System.out.println("str是否以Java开头:"+str.startsWith("Java")); System.out.println("str是否以Java结尾:"+str.endsWith("Java")); System.out.println("从2开始截取str:"+str.substring(2)); System.out.println("从2到6截取str:"+str.substring(2, 6)); System.out.println("将str中的World替换为Java:"+str.replaceAll("World", "Java")); System.out.println("用逗号分割str:"+Arrays.toString(str.split(","))); System.out.println("将str转为char类型数组:"+Arrays.toString(str.toCharArray())); System.out.println("str3转为小写:"+str3.toLowerCase()); System.out.println("str2转为大写:"+str2.toUpperCase()); } }运行结果为:
Java,Hello,World
str长度:16
str是否为空:false
下标为2的字符是:v
H的下标是:5
str和str2是否相等:false
str2和str3忽略大小写是否相等:true
str是否以Java开头:true
str是否以Java结尾:false
从2开始截取str:va,Hello,World
从2到6截取str:va,H
将str中的World替换为Java:Java,Hello,Java
用逗号分割str:[Java, Hello, World]
将str转为char类型数组:[J, a, v, a, , H, e, l, l, o, , W, o, r, l, d]
str3转为小写:hello
str2转为大写:HELLO