Java字符串(三十八)
字符串是 Java 中特殊的类,使用方法像一般的基本数据类型,被广泛应用在 Java 编程中。Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个 String 类来创建和操作字符串。
—— String 类位于 java.lang 包中。默认情况下,该包被自动导入所有的程序。
在 Java 中定义一个字符串最简单的方法是用双引号把它包围起来。这种用双引号括起来的一串字符实际上都是 String 对象,如字符串“Hello”在编译后即成为 String 对象。因此也可以通过创建 String 类的实例来定义字符串。
不论使用哪种形式创建字符串,字符串对象一旦被创建,其值是不能改变的,但可以使用其他变量重新赋值的方式进行更改。
定义字符串的2种方式:
直接定义字符串
直接定义字符串是指使用双引号表示字符串中的内容,例如“Hello Java”、“Java 编程”等。具体方法是用字符串常量直接初始化一个 String 对象,示例如下:
- String str = "Hello Java";
或者
- String str;
- str = "Hello Java";
注意:字符串变量必须经过初始化才能使用。
使用 String 类定义
在 Java 中每个双引号定义的字符串都是一个 String 类的对象。因此,可以通过使用 String 类的构造方法来创建字符串,该类位于 java.lang 包中。
注意:具有和类名相同的名称,而且没有返回类型的方法称为构造方法。重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
-
String()
初始化一个新创建的 String 对象,表示一个空字符序列。
-
String(String original)
初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列。换句话说,新创建的字符串是该参数字符串的副本。
例如:
String str1 = new String("Hello Java");
String str2 = new String(str1);
这里 str1 和 str2 的值是相等的。
-
String(char[ ]value)
分配一个新的字符串,将参数中的字符数组元素全部变为字符串。该字符数组的内容已被复制,后续对字符数组的修改不会影响新创建的字符串。
例如:
char a[] = {'H','e','l','l','0'};
String sChar = new String(a);
a[1] = 's';
上述 sChar 变量的值是字符串“Hello”。 即使在创建字符串之后,对 a 数组中的第 2 个元素进行了修改,但未影响 sChar 的值。
- String(char[] value,int offset,int count)
分配一个新的 String,它包含来自该字符数组参数一个子数组的字符。offset 参数是子数组第一个字符的索引,count 参数指定子数组的长度。该子数组的内容已被赋值,后续对字符数组的修改不会影响新创建的字符串。
例如:
char a[]={'H','e','l','l','o'};
String sChar=new String(a,1,4);
a[1]='s';
上述 sChar 变量的值是字符串“ello”。该构造方法使用字符数组中的部分连续元素来创建字符串对象。offset 参数指定起始索引值,count 指定截取元素的个数。创建字符串对象后,即使在后面修改了 a 数组中第 2 个元素的值,对 sChar 的值也没有任何影响。
String类的常用方法:
提示:
- 字符串 str 中字符的索引从0开始,范围为 0 到 str.length()-1
- 使用 indexOf 进行字符或字符串查找时,如果匹配返回位置索引;如果没有匹配结果,返回 -1
- 使用 substring(beginIndex , endIndex) 进行字符串截取时,包括 beginIndex 位置的字符,不包括 endIndex 位置的字符
package com.example.demo; public class HelloWorld { public static void main(String[] args) { String fileName = "HelloWorld.java"; // Java文件名 String email = "xxxxxx@163.com"; // 邮箱 // 判断.java文件名是否正确:合法的文件名应该以.java结尾 /* 参考步骤: 1、获取文件名中最后一次出现"."号的位置 2、根据"."号的位置,获取文件的后缀 3、判断"."号位置及文件后缀名 */ int index = fileName.lastIndexOf("."); //获取文件名中最后一次出现"."号的位置 String prefix = fileName.substring(index); // 获取文件的后缀 if (index > 0 && (prefix.equals(".java")) ) { // 判断必须包含"."号,且不能出现在首位,同时后缀名为"java" System.out.println("Java文件名正确"); } else { System.out.println("Java文件名无效"); } // 判断邮箱格式是否正确:合法的邮箱名中至少要包含"@", 并且"@"是在"."之前 /* 参考步骤: 1、获取文件名中"@"符号的位置 2、获取邮箱中"."号的位置 3、判断必须包含"@"符号,且"@"必须在"."之前 */ int index2 = email.indexOf("@"); // 获取邮箱中"@"符号的位置 int index3 = email.indexOf('.'); // 获取邮箱中"."号的位置 if (index2 != -1 && index3 > index2) { // 判断必须包含"@"符号,且"@"必须在"."之前 System.out.println("邮箱格式正确"); } else { System.out.println("邮箱格式无效"); } } }
运行结果:
public class HelloWorld { public static void main(String[] args) { String str = "学习JAVA"; //定义一个字符串“学习” System.out.println("转换为小写:"+str.toLowerCase()); //将字符串转换为小写 System.out.println("获取索引为1位置的字符:"+str.charAt(1)); //获取索引位置为1的字符 byte[] b = str.getBytes(); //将字符串转换为byte[],并打印输出 System.out.println("转换为字节数组:"); for (int i = 0; i < b.length; i++) { System.out.println(b[i]); } System.out.println(); // 和另外一个字符串“学习JAVA”进行比较 String str2 = new String("学习JAVA"); System.out.println("str和str2的内存地址相同?"+(str==str2)); System.out.println("str和str2的内容相同?"+str.equals(str2)); } }
运行结果:
public static void main(String[] args) { // 定义一个字符串 String s = "aljlkdsflkjsadjfklhasdkjlflkajdflwoiudsafhaasdasd"; // 出现次数 int num = 0; // 循环遍历每个字符,判断是否是字符 a ,如果是,累加次数 for (int i = 0;i < s.length();i++) { // 获取每个字符,判断是否是字符a if ( s.charAt(i) == 'a' ) { // 累加统计次数 num++; } } System.out.println("字符a出现的次数:" + num); } }
运行结果:
“==” 和 equals() 的区别:
==:判断两个字符串在内存中地址是否相同,即判断是否是同一个字符串对象
equals(): 比较存储在两个字符串对象中的内容是否一致
StringBuilder 类
在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。String 类是不可变类,即一旦一个 String 对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。
Java 提供了两个可变字符串类 StringBuffer 和 StringBuilder,中文翻译为“字符串缓冲区”。
StringBuilder 和 StringBuffer 功能基本相似,方法也差不多。不同的是,StringBuffer 是线程安全的,而 StringBuilder 则没有实现线程安全功能,所以性能略高。
因此在通常情况下,如果需要创建一个内容可变的字符串对象,则应该优先考虑使用 StringBuilder 类。
StringBuffer、StringBuilder、String 中都实现了 CharSequence 接口。CharSequence 是一个定义字符串操作的接口,它只包括 length()、charAt(int index)、subSequence(int start, int end) 这几个 API。
StringBuffer、StringBuilder、String 对 CharSequence 接口的实现过程不一样,如图 :
例如:
运行结果: hello
总结:
String 是 Java 中基础且重要的类,被声明为 final class,是不可变字符串。因为它的不可变性,所以拼接字符串时候会产生很多无用的中间对象,如果频繁的进行这样的操作对性能有所影响。
StringBuffer 就是为了解决大量拼接字符串时产生很多中间对象问题而提供的一个类。它提供了 append 和 add 方法,可以将字符串添加到已有序列的末尾或指定位置,它的本质是一个线程安全的可修改的字符序列。
在很多情况下我们的字符串拼接操作不需要线程安全,所以 StringBuilder 登场了。StringBuilder 是 JDK1.5 发布的,它和 StringBuffer 本质上没什么区别,就是去掉了保证线程安全的那部分,减少了开销。
线程安全:
StringBuffer:线程安全
StringBuilder:线程不安全
速度:
一般情况下,速度从快到慢为 StringBuilder > StringBuffer > String,当然这是相对的,不是绝对的。
使用环境:
操作少量的数据使用 String。
单线程操作大量数据使用 StringBuilder。
多线程操作大量数据使用 StringBuffer。
StringBuilder 类提供了很多方法来操作字符串:
例如:
在下面的代码中,创建了 StringBuilder 对象,用来存储字符串,并对其做了追加和插入操作。这些操作修改了 str 对象的值,而没有创建新的对象,这就是 StringBuilder 和 String 最大的区别。
运行结果:
运行结果: