在编程中,我们经常需要处理字符串。字符串在许多应用中都非常常见,如用户输入、文本处理、文件操作等。Java 提供了String类来处理这些字符串数据。无论是存储文本、进行字符串的拼接、查找、替换,还是对字符串进行格式化和比较,String类都提供了非常强大的功能。
在很多编程语言中,字符串都是作为一个基础数据类型存在的。然而,在 Java 中,字符串是一个对象,它是String类的实例。
1.什么是String类?
String类是 Java 中用于表示字符串的类,它是 Java 核心库的一部分。String是一个不可变(immutable)类,这意味着一旦创建一个String对象,其内容不能被修改。如果对字符串内容进行修改,实际上会创建一个新的String对象。
主要特点:
- 不可变性:一旦创建,
String对象的内容不能修改。任何对String的修改操作都会创建一个新的String对象。 - 内存优化:由于
String是不可变的,JVM 会对字符串常量池进行优化,共享相同的字符串常量,节省内存。 - 高效的字符串操作:
String类提供了许多操作方法,使得字符串的操作更加简洁、直接和高效。 - 补充:
1.String 对象用于保存字符串,也就是一组字符序列
2."jack”字符串常量,双引号括起的字符序列
3.字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
4.String 类有很多构造器,构造器的重载
常用的有 String s1=new String();//
String s2=new string(string original);
Strings3 = new String(char[ ] a);
Strings4 = new String(char[ ] a,int startIndex,int count);
String s5 = new string(byte[ ] b);
5.String 类实现了接口 Serializable:String 可以串行化:可以在网络传输
实现了接口 Comparable:String 对象可以比较大小
6.String 是final 类,不能被其他的类继承,
2.创建String类的两种方式
- 方式一:直接赋值 String s= "hsp";
先从常量池查看是否有 "hsp" 数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址。
- 方式二:调用构造器 String s= new String("hsp”);
先在堆中创建空间,里面维护了value属性,value属性指向常量池的hsp空间。如果常量池没有"hsp”,重新创建,如果有,直接通过value指向。s指向的是堆中的空间地址,也就是value属性,value属性指向常量池的hsp地址,多了一个中间商。
3.String对象特性
public class StringExercise08{ public static void main(string[] args){ String a="hello";//创建 a对象 String b="abc"://创建 b对象 //老韩解读 //1.先创建一个 stringBuilder sb = stringBuilder() //2.执行sb.append("hello"); //3.执行sb.append("abc"); //4.string c= sb.tostring() //最后其实是c指向堆中的对象(String)value[]->指向池中"helloabc' String c = a + b; } }重要规则:
string c1 ="ab"+"cd"。常量相加,看的是池。 String c1 =a + b;变量相加,是在堆中。
4.String常用方法
String类的常见方法一览[了解即可]
- equals // 区分大小写,判断内容是否相等
- equalslgnoreCase // 忽略大小写的判断内容是否相等
- length // 获取字符的个数,字符串的长度
- indexOf //获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1
- lastlndexOf //获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回-1
- substring //截取指定范围的子串
substring(0,5)表示从索引0开始截取,截取到索引 5-1 位置(截取5个字符)
- trim //去前后空格
- charAt:获取某索引处的字符,注意不能使用Str[index] (数组)这种方式获取字符
eg:String str = "hello” ;
//str[0] 不对
//str.charAt(0) => h
- toUpperCase // 把字符转换成大写
- toLowerCase //把字符转换成小写
- concat // 拼接字符串
- replace // 替换字符串中的字符
public class test { public static void main(String[] args) { s1 = "宝玉 and 林黛玉 林黛玉 林黛玉”; //在s1中,将所有的林黛玉替换成薛宝钗 s2 = s1.replace("林黛玉","薛宝钗"); System.out.println(s2);//宝玉 and 薛宝钗 薛宝钗 薛宝钗 //解读:s1.replace()方法执行后,返回的结果才是替换过的。注意,对 s1 没有任何影响,因为是s2接收的,如果是s1接收的s1才变化了 } }- split //分割字符串
- toCharArray // 转换成字符数组
s ="happy"; char[] chs = s.tocharArray(); for(int i=0;i< chs.length; i++){ System.out.println(chs[i]) }- compareTo //比较两个字符串的大小(ascll码值),如果前者大,则返回正数,后者大,则返回负数,如果相等,返回0。
- format 格式化字符串
5.Stringbuffer类
在 Java 中,String是一个不可变类,也就是说每次对字符串进行修改操作(例如拼接)时,都会创建一个新的String对象。这就导致了一个问题:如果我们在循环中或频繁地进行字符串拼接操作,程序会产生大量的临时对象,从而浪费内存并影响性能。
为了更高效地进行字符串拼接和修改,Java 提供了StringBuffer类,它是一个可变的字符序列,能够在不创建新对象的情况下对字符串进行修改和操作。
特点:
- StringBuffer 继承 AbstractstringBuilder 类
- StringBuffer 实现了Serializable,即StringBuffer的对象可以串行化(可以网络传输 或 保存在文件中)
- 在父类中 AbstractStringBuilder 有属性 char[ ]value,该属性不是final; 该value 数组存放字符串内容,位置存放在堆中的。
- StringBuffer是一个final类,不能被继承
- 因为StringBuffer字符内容是存在char[ ]value,所有在变化(增加/删除)不用每次都更换地址(即不是每次创建新对象),所以效率高于String
构造器的使用:
1.父类会创建一个 大小为16的 char[ ] 用于存放字符内容
StringBuffer stringBuffer = new StringBuffer();2.通过构造器指定 char[ ]大小
StringBuffer stringBuffer = new StringBuffer(100);3.通过 给一个String 创建StringBuffer,char[ ]大小就是 str.length() + 16
StringBuffer hello = new StringBuffer("hello");1.String和StringBuffer相互转换
(1)String ——> StringBuffer
- 方式1 使用构造器
注意:返回的才是StringBuffer对象,对str本身没有影响
String str ="hello tom"; StringBuffer stringBuffer = new StringBuffer(str);- 方式2 使用append方法
StringBuffer stringBuffer1 = new stringBuffer(); stringBuffer1 = stringBuffer1.append(str);(2) StringBuffer ——> String
- 方式1 使用StringBuffer提供的 toString方法
StringBuffer stringBuffer3 = new StringBuffer("韩顺平教育") String s= stringBuffer3.tostring();- 方式2 使用构造器
String s1 = new String(stringBuffer3);2.StringBuffer类常用方法
创建
StringBuffer对象:StringBuffer sb1 = new StringBuffer(); // 创建空的 StringBuffer StringBuffer sb2 = new StringBuffer("Hello"); // 创建并初始化为 "Hello" StringBuffer sb3 = new StringBuffer(50); // 创建指定初始容量的 StringBuffer追加字符串:
append()方法用于将指定的字符串追加到StringBuffer的末尾。StringBuffer sb = new StringBuffer("Hello"); sb.append(" World"); // 追加 " World" 后,sb 的内容变为 "Hello World"插入字符串:
insert()方法可以将字符串插入到指定的位置。StringBuffer sb = new StringBuffer("Hello World"); sb.insert(6, "Java "); // 在索引 6 处插入 "Java ",sb 的内容变为 "Hello Java World"删除字符串:
delete()方法可以删除指定范围内的字符。StringBuffer sb = new StringBuffer("Hello World"); sb.delete(5, 11); // 删除从索引 5 到 10 的字符,sb 的内容变为 "Hello"
[5,11)左闭右开
替换字符串:
replace()方法可以替换指定范围内的字符。StringBuffer sb = new StringBuffer("Hello World"); sb.replace(6, 11, "Java"); // 将索引 6 到 10 的部分替换为 "Java",sb 的内容变为 "Hello Java"
[6,11)左闭右开
反转字符串:
reverse()方法可以将StringBuffer中的字符顺序反转。StringBuffer sb = new StringBuffer("Hello"); sb.reverse(); // sb 的内容变为 "olleH"
获取字符长度:
length()方法返回StringBuffer中当前字符的长度。StringBuffer sb = new StringBuffer("Hello"); int length = sb.length(); // 返回 5
6.StringBuilder类
在 Java 中,String类是不可变的,每次对字符串进行修改操作(例如拼接、插入、替换等)时,都会创建一个新的String对象。这种特性在某些情况下可能导致性能问题,尤其是当我们需要进行频繁的字符串拼接操作时。每次修改都会创建新的对象,不仅浪费内存,也会降低效率。
为了解决这个问题,Java 提供了StringBuilder类,它是一个可变的字符序列,专门用于高效地进行字符串拼接、插入、删除等操作。StringBuilder类是StringBuffer类的简易替换,StringBuilder也能够避免每次修改时都创建新的对象,但与StringBuffer不同的是,StringBuilder不是线程安全的,因此在单线程环境下性能更好,单线程情况可优先使用。
特点:
- StringBuilder 继承 AbstractStringBuilder类
- 实现了 Serializable,说明StringBuilder对象是可以串行化(对象可以网络传输,可以保存到文件)
- StringBuilder 是final类,不能被继承
- StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder的 char[ ]value;因此,字符序列是存在堆中
- StringBuilder 的方法,没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下推荐使用StringBuilder
7.String类,StringBuffer类,StringBuilder类三类比较
- StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且方法也一样
- String:不可变字符序列,效率低,但是复用率高。
- StringBuffer:可变字符序列、效率较高(增删)、线程安全
- StringBuilder:可变字符序列、效率最高、线程不安全
- String使用注意说明:
string s = "a";//创建了一个字符串s+ = "b";//实际上原来的"a"字符串对象已经丢弃了,现在又产生了一个字符串s+"b"(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能 。
小结:如果我们需要对 String 做大量修改,不要使用String
总结,使用的原则:
- 如果字符串存在大量的修改操作,一般使用 StringBuffer 或StringBuilder
- 如果字符串存在大量的修改操作,并在单线程的情况,使用 StringBuilder
- 如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer
- 如果字符串很少修改,被多个对象引用,使用String,比如配置信息等