String、StringBuffer和StringBuilder

一、String类

1. String类的介绍和创建对象

  1. String对象用于保存字符串,也就是一组字符序列。

  2. 常量对象:字符串常量对象是用双引号括起的字符序列。例如:“你好”、“12.97”、"boy"等。

  3. 字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节。

  4. String类较常用构造器。

    String  s1 = new String();
    String  s2 = new String(String original);
    String  s3 = new String(char[] a);
    String  s4 = new String(char[] a,int startIndex,int count);
    
  5. 源码
    在这里插入图片描述

2. 创建String对象的两种方式

方式一:直接赋值	String s1 = "hello"; 
方式二:调用构造器	String s2 = new String("hello"); 

3. 两种创建String对象的区别

在这里插入图片描述

3.1 方式一
  • 先从常量池查看是否有“hello” 数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s1最终指向的是常量池的空间地址。
3.1 方式二
  • 1)先在堆中创建空间,里面维护了value属性,指向常量池的hello空间。如果常量池没有“hello”,重新创建,如果有,直接通过value指向。s2最终指向的是堆中的空间地址。
3.3 测试
String a = new String("abc");
String b =new String("abc");
System.out.println(a.equals(b));//true
System.out.println(a==b); // false
String a = "abc";
String b =new String("abc");
System.out.println(a.equals(b)); //真
System.out.println(a==b); //假
System.out.println(a==b.intern());//真  intern 表示获取常量
System.out.println(b==b.intern()); // 假
知识点:
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用
解读:(1) b.intern() 方法最终返回的是常量池的地址(对象)。
String s1 = "hello";
String s2 = "java";
String s4 = "java";
String s3 = new String("java");
System.out.println(s2 == s3); //F  分析 s2指向常量池 s3指向堆
System.out.println(s2 == s4); //T  s2 和 s4 指向常量池,并是同一个常量
System.out.println(s2.equals(s3));// 比较内容, 真
Person p1 = new Person();
p1.name = "hello";
Person p2 = new Person();
p2.name = "hello";

System.out.println(p1.name.equals(p2.name));  // 真,比较内容
System.out.println(p1.name == p2.name); // 真 p1.name 和 p2.name 指向常量池, 并是同一个常量 
System.out.println(p1.name == "hello");  //真,  p1.name 和 “hello” 常量池 

String s1 = new String("bcde");
String s2 = new String("bcde");
System.out.println(s1==s2); // 假 s1 指向堆 s2指向堆, 不是同一个对象

4. 字符串的特性

4.1 介绍
  • String是一个final类,代表不可变的字符序列。
  • 字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的。
4.2 面试题(1)
String a ="hello" + "abc"; 创建了几个对象?
// 只有一个对象 1个对象

分析:

  1. 编译器底层会做优化。
  2. String a =“hello” + “abc”; ==> String a = “helloabc”;
4.3 面试题(2)
String a = "hello";
String b = "abc";
String c = a + b;
创建了几个对象?
// 3个对象

分析:

  1. 变量相加时, a + b 时,底层使用的 StringBuilder, 内容在堆。

  2. String c = a + b;
    底层是 StringBuilder sb = new StringBuilder(a); sb.append(b); sb是在堆中,并且append是在原来字符串的基础上追加的。
    
  3. 规则:

    String c1 = "ab" + "cd";常量相加,看的是池。String c1 = a + b; 变量相加,是在堆中。
    
4.3 面试题(3)
String s1 = "hello";      //s1 常量池
String s2 = "java";         // s2 常量池
String s5 = "hellojava";          // s5 常量池
String s6 = (s1 + s2).intern();   // s6 指向 常量池
System.out.println(s5 == s6);       // T 【s5 和 s6 的内容相同,并且都指向池】
System.out.println(s5.equals(s6));  // T 【内容,相等的】

5. String类的常见方法

String类是保存字符串常量的,每次更新都需要重新开辟空间,效率较低,因此java设计者还提供了StringBuilder 和 StringBuffer 来增强String的功能,并提高效率。

方法方法说明
equals区分大小写,判断内容是否相等
equalsIgnoreCase忽略大小写的判断内容是否相等
length获取字符的个数,字符串的长度
indexOf获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1
lastIndexOf获取字符在字符串中最后1次出现的索引,索引从0开始,如果找不到,返回-1
substring截取指定范围的子串
trim去前后空格
charAt获取某索引处的字符,注意不能使用Str[index] 这种方式
toUpperCase转换成大写
toLowerCase转换成小写
concat拼接字符串
compareTo比较两个字符串的大小,如果前者大,则返回正数,后者大,则返回负数,如果相等,返回0

二、StringBuffer类

1. 介绍

  • java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删。

  • 很多方法与String相同,但StringBuffer是可变长度的。

  • StringBuffer是一个容器。
    在这里插入图片描述

2. String和StringBuffer的对比

  • String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低。

    private final char value[]; 
    
  • StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用更新地址,效率较高。

    private transient char[] toStringCache;  // 这个放在堆
    

3. StringBuffer的构造器

在这里插入图片描述

4. String和StringBuffer相互转换

4.1 String 转 StringBuffer
String s = "hello";
// 方式一
StringBuffer sb1 = new StringBuffer(s);
// 方式二
StringBuffer sb2 = new StringBuffer();
sb2.append(s);
4.2 StringBuffer 转 String
StringBuffer sb = new StringBuffer("hello");
// 方式一
String s1 = sb.toString();
// 方式二
String s2 = new String(sb);

5. StringBuffer类常见方法

方法方法说明
append
delete(start,end)
replace(start,end,string)改,start —— end 间的内容替换掉,不含end
indexOf查,查找子串在字符串第1次出现的索引,如果找不到返回-1
insert插入
length获取长度

三、StringBuilder类

1. 介绍

  • 一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步【多并发+多线程】,1)该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快
  • 在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串生成器中。append 方法始终将这些字符添加到生成器的末端;而 insert 方法则在指定的点添加字符。

2. StringBuilder常用方法

StringBuilder 和 StringBuffer 均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样。

3. String、StringBuffer和StringBuilder的比较

  1. StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且方法也一样.

  2. String:不可变字符序列,效率低,但是复用率高。

  3. StringBuffer:可变字符序列、效率较高(增删)、线程安全。

    在这里插入图片描述

  4. StringBuilder(JDK1.5):可变字符序列、效率最高、线程不安全(方法没有用synchronized关键字修饰)。

在这里插入图片描述

线程安全适用场景字符序列
String少量字符串操作的场景不可变
StringBuffer线程安全多线程下在字符缓冲区进行大量操作的场景可变
StringBuilder线程不安全单线程下在字符缓冲区进行大量操作的场景可变

运行速度快慢

StringBuilder > StringBuffer > String

----- |
| String | | 少量字符串操作的场景 | 不可变 |
| StringBuffer | 线程安全 | 多线程下在字符缓冲区进行大量操作的场景 | 可变 |
| StringBuilder | 线程不安全 | 单线程下在字符缓冲区进行大量操作的场景 | 可变 |

运行速度快慢

StringBuilder > StringBuffer > String
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值