String/StringBuffer/StringBuilder的不详细解释和用法区别

本文详细介绍了Java中的String类,包括其不可变性、创建方式、常量池、常用方法及“+”运算的原理。同时,对比分析了StringBuffer和StringBuilder在效率和线程安全上的差异,适合Java程序员面试复习。
摘要由CSDN通过智能技术生成


前言

提示:StringBuffer和StringBuilder经常面试问


一、String

1.1 概述

在这里插入图片描述
String:字符串本质是字符数组(字符序列)
String类 - 字符串

特点:
a.字符串就是字符序列,本质上就是一个字符数组
b.String类是final修饰的,不可被继承的
c.String一旦创建就不可修改,属于不可变的字符序列
d.String重写了toString()

1.2 创建方式

a.直接创建
	String str = "";

本质是指向字符串常量池中同一段字符串
在这里插入图片描述

b.构造方法创建
	String() 
	String(byte[] bytes) 
	String(byte[] bytes, Charset charset) 
	String(char[] value) 
	String(String original) 

new出来的对象都是放在堆里的,故比较地址并不相等
在这里插入图片描述

1.3 常量池

在Java的内存分配中,总共3种常量池,分别是Class常量池、运行时常量池、字符串常量池。

a.常量池中放的都是常量
b.只要直接赋值的字符串,都指向常量池
(new 出来的不是放在常量池)

在这里插入图片描述

1.4 常用方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

运行结果:
在这里插入图片描述

1.5 “+”运算

Java语言为“+”连接符以及对象转换为字符串提供了特殊的支持,字符串对象可以使用“+”连接其他对象。其中字符串连接是通过 StringBuilder(或 StringBuffer)类及其append 方法实现的,对象转换为字符串是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。Java中使用"+"连接字符串对象时,会创建一个StringBuilder()对象,并调用append()方法将数据拼接,最后调用toString()方法返回拼接好的字符串。****两个常量进行“+”操作,java会直接进行优化成拼接后的字符串常量,而两个变量进行“+”操作,在编译器不会对引用变量进行优化。


在这里插入图片描述
在这里插入图片描述

1.5.1intern()

intern 方法是一个native方法,intern方法会从字符串常量池中查询当前字符串是否存在,如果存在,就直接返回当前字符串;如果不存在就会将当前字符串放入常量池中,之后再返回。

1.6 乱码问题

内存编码问题

1)编码方式:
	UniCode字符集 -> jvm识别
		1字符 = 2字节

	操作系统识别的编码方式: GBK UTF-8 ASCII ISO8859-1
		UTF-8 -> 1字符 = 3字节
		GBK -> 1字符 = 2字节

2)编码: 字符 -> 字节
	API:
		byte[]   str.getBytes() -> 默认方式
		byte[]   str.getBytes("GBK") -> 指定方式

3)解码: 字节 -> 字符
	构造方法:
		new String(byte[],"GBK")
		new String(byte[])

4)乱码问题:
	a.产生原因:
		如果以gbk的方式编码得到的数组,然后以UTF-8的方式进行解码,就会出现乱码问题
	b.解决乱码:
		1.按照错误的方式进行编码
		2.得到字节数组,在重新解码

二、StringBuffer与StringBuilder

在这里插入图片描述

2.1概述

1.StringBuilder 和 StringBuffer

 StringBuilder 和 StringBuffer都是属于可变长字符串[在改变字符串的时候,不会产生新的对象]

2.创建:

	new StringBuilder()
	new StringBuilder(String s)

3.常用API:

  StringBuilder  append(Object obj)  - 追加
  StringBuilder  delete(int start, int end)  - 删除(前包含后不包含)
  StringBuilder  insert(int offset, boolean b)   - 插入(前包含后不包含)
  StringBuilder  replace(int start, int end, String str)  - 替换(前包含后不包含)
  StringBuilder  reverse()  - 反转

4.区别:

a.版本:
	StringBuilder -> JDK1.5
	StringBuffer  -> JDK1.0

b.线程安全
	StringBuilder: 线程不安全,效率高
	StringBuffer:  线程安全,效率低

c.使用环境:
	操作少量的数据使用 String
	单线程环境下大量数据使用 StringBuilder
	多线程环境下大量数据使用 StringBuffer

d.效率对比
	String < StringBuffer < StringBuilder

2.2 效率对比

StringBulider > StringBuffer > String
在这里插入图片描述
1.String 类型和 StringBuffer、 StringBuild类型的主要性能区别其实在于 String 是不可变的对象(final), 因此在每次对 String 类型进行改变的时候其实都等同于在堆中生成了一个新的 String 对象,然后将指针指向新的 String 对象,这样不仅效率低下,而且大量浪费有限的内存空间,所以经常改变内容的字符串最好不要用 String 。因为每次生成对象都会对系统性能产生影响,特别是当内存中的无引用对象过多了以后, JVM 的 GC 开始工作,那速度是一定会相当慢的。另外当GC清理速度跟不上new String的速度时,还会导致内存溢出Error,会直接kill掉主程序!

2.我们一般在StringBuffer、StringBuild类上的主要操作是 append 和 insert 方法,这些方法允许被重载,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点(index)添加字符。他们俩均属于字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,这样就不会像String一样创建一些而外的对象进行操作了,速度自然就相对快了。

2.3 线程安全

StringBuffer的很多方法都被关键字synchronized 修饰了,而StringBuilder没有。

synchronized的含义:
  每一个类对象都对应一把锁,当某个线程A调用类对象O中的synchronized方法M时,必须获得对象O的锁才能够执行M方法,否则线程A阻塞。一旦线程A开始执行M方法,将独占对象O的锁。使得其它需要调用O对象的M方法的线程阻塞。只有线程A执行完毕,释放锁后。那些阻塞线程才有机会重新调用M方法。这就是解决线程同步问题的锁机制。了解了synchronized的含义以后,大家可能都会有这个感觉。多线程编程中StringBuffer比StringBuilder要安全多了 ,事实确实如此。如果有多个线程需要对同一个字符串缓冲区进行操作的时候,StringBuffer应该是不二选择。
  
注意:是不是String也不安全呢?事实上不存在这个问题,String是不可变的。线程对于堆中指定的一个String对象只能读取,无法修改。

在这里插入图片描述


总结

String掰开揉碎也就那么点东西,一个类也问不了多深奥的问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值