目录
5 String,StringBuffer,StringBuilder比较
1.包装类
基本数据类型 | 包装类 |
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
(黄色包装类的父类:Number) |
1.1 装箱和拆箱
装箱:基本数据类型->包装类,拆箱反之,自动装箱拆箱在(jdk5之后)才有
装箱:
- 手动装箱=new 包装类(基本数据类型变量) 或 包装类.valueOf()
- 自动装箱 直接赋值(实际走的还是valueof)
拆箱:
- 拆箱 手动(xxx name = (包装类对象).xxxvalue)
- 自动拆箱 直接赋值(走的还是xxxvalue)
class PackageClass_{
public static void main(String[] args) {
//手动装箱
int a = 10;
Integer A1 = new Integer(a);
Integer A2 = Integer.valueOf(a);
//自动装箱
Integer A3 = a;
//手动拆箱
int a1 = A1.intValue();
//自动拆箱
int a3 = A3;
}
}
1.2包装类方法
//手动拆箱到 xxx 基本数据类型
xxxValue();
//手动装箱到包装类 //String转换到包装类
valueOf((xxx) i);
//转换到String
toString();
2.String
Unicode编码,一个字符占两个字节
final 类,不能被继承
实现了serializable接口和comparable接口,具有串行化网络传输和进行数据比较的性质
2.1 String的保存属性
![](https://img-blog.csdnimg.cn/61721d6664824e5db2f1ed152c09f3bf.png)
2.2 String的创建方式
直接赋值(先从常量池查看有没有“xxx“的数据空间,有的话,直接指向,没有则重新创建然后指向,对象最后指向的是它的地址(常量池))
![]()
常量池地址一样 //直接赋值创建 String str1 = "abc"; String str4 = "abc";
使用构造器(先从堆中创建空间,堆的该空间里面维护value的属性,然后从常量值里找,没有则创建,将改地址赋值给value,堆的该地址指向创建的对象)
//使用构造器 String str2 = new String("abc");
2.3 String关于“==”特性的比较
2.3.1 字符串的特性
字符串不可变,一个字符串一旦被分配,其内容将不可变,一旦重新赋值等价于重新将地址赋给对象
![]()
改变str1的字符串,可见改变了value的指向地址
2.3.2 编译器优化
编译器会判断引用对象并进行优化,避免无用的创建对象;
String str3 = "a" + "bc";
2.3.3 地址比较
字符串==比较:常量相加看池地址,变量相加看堆地址
public class PClass {
public static void main(String[] args) {
//直接赋值创建
String str1 = "abc";
//str1 = "abcd";
String str4 = "abc";
//使用构造器
String str2 = new String("abc");
String str3 = "a" + "bc";
String str5 = new String("a");
String str6 = new String("bc");
String str7 = str5 +str6;
System.out.println(str1 == str3); //true
System.out.println(str1 == str4); //true
System.out.println(str1 == str2); //false
System.out.println(str1 == str7); //false
System.out.println(str2 == str7); //false
}
2.3.4 值比较
equals方法,或者intern()
System.out.println(str1.equals(str7));
System.out.println(str7.intern() == str2.intern());
2.4 String常用方法
equals 区分大小写,判断内容是否相等
equalslgnoreCase 忽略大小写的判断内容是否相等
length 获取字符的个数,字符串的长度
indexOf 获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回
lastIndexOf 获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回-1
substring 截取指定范围的子串
trim 去空格
charAt 获取某索引处的字符,注意不能使用Str[index]这种方式.
3.StringBuffer
StringBuffer sb1 = new StringBuffer(10);
- 线程安全,可变的字符序列。 字符串缓冲区就像一个String ,但可以修改。 在任何时间点,它包含一些特定的字符序列,但可以通过某些方法调用来更改序列的长度和内容。
![]()
不是final因此存放在堆中(ToString返回的最后一个值的缓存。每当StringBuffer被修改时清除。) - 字符串缓冲区可以安全地被多个线程使用。 这些方法在必要时进行同步,以便任何特定实例上的所有操作都按照与所涉及的各个线程所执行的方法调用顺序一致的顺序发生。
- StringBuffer的主要
StringBuffer
是append
和insert
方法,它们被重载以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符附加或插入到字符串缓冲区。append
方法总是在缓冲区的末尾添加这些字符;insert
方法将insert
添加到指定点。- 例如,如果
z
是指当前内容为"start"
的字符串缓冲区对象,那么方法调用z.append("le")
将使字符串缓冲区包含"startle"
,而z.insert(4, "le")
会将字符串缓冲区更改为包含"starlet"
。- 一般情况下,如果某人是指的一个实例
StringBuffer
,则sb.append(x)
具有相同的效果sb.insert(sb.length(), x)
。- 每当涉及源序列(例如从源序列追加或插入)的操作发生时,该类仅在执行操作的字符串缓冲器上进行同步,而不在源上。 请注意,虽然
StringBuffer
被设计为可以安全地从多个线程并发使用,但如果构造函数或append
或insert
操作被传递通过线程共享的源序列,则调用代码必须确保该操作具有一致且不变的视图在操作期间的源序列。 呼叫者通过使用不可变的源序列,或者不跨线程共享源序列,可以在呼叫期间持有锁来满足这一点。- 每个字符串缓冲区都有一个容量。 只要字符串缓冲区中包含的字符序列的长度不超过容量,就不必分配新的内部缓冲区数组。 如果内部缓冲区溢出,则会自动变大。(更新是更新内容,当容器量不够时才会更新地址,所以效率较高)
- 除非另有说明,否则将
null
参数传递给null
中的构造函数或方法将导致抛出NullPointerException 。- 从版本JDK 5开始,这个类别已经被一个等级类补充了,这个类被设计为使用一个线程StringBuilder 。
StringBuilder
应该使用StringBuilder
类,因为它支持所有相同的操作,但它更快,因为它不执行同步。
3.1 StringBuffer常用方法
主要是增(append)删(delete)查(indexOf)改(replace)插(insert)
StringBuffer
append(boolean b)
将
boolean
参数的字符串表示附加到序列中。StringBuffer
append(char c)
将
char
参数的字符串表示附加到此序列。StringBuffer
append(char[] str)
将
char
数组参数的字符串表示附加到此序列。StringBuffer
append(char[] str, int offset, int len)
将
char
数组参数的子阵列的字符串表示附加到此序列。StringBuffer
append(CharSequence s)
追加指定的
CharSequence
到这个序列。StringBuffer
append(CharSequence s, int start, int end)
追加指定的序列
CharSequence
到这个序列。StringBuffer
append(double d)
将
double
参数的字符串表示附加到此序列。StringBuffer
append(float f)
将
float
参数的字符串表示附加到此序列。StringBuffer
append(int i)
将
int
参数的字符串表示附加到此序列。StringBuffer
append(long lng)
将
long
参数的字符串表示附加到此序列。StringBuffer
append(Object obj)
追加
Object
参数的字符串表示。StringBuffer
append(String str)
将指定的字符串附加到此字符序列。
StringBuffer
append(StringBuffer sb)
将指定
StringBuffer
这个序列。StringBuffer
appendCodePoint(int codePoint)
将
codePoint
参数的字符串表示法附加到此序列。int
capacity()
返回当前容量。
char
charAt(int index)
返回
char
在指定索引在这个序列值。int
codePointAt(int index)
返回指定索引处的字符(Unicode代码点)。
int
codePointBefore(int index)
返回指定索引之前的字符(Unicode代码点)。
int
codePointCount(int beginIndex, int endIndex)
返回此序列指定文本范围内的Unicode代码点数。
StringBuffer
delete(int start, int end)
删除此序列的子字符串中的字符。
StringBuffer
deleteCharAt(int index)
删除
char
在这个序列中的指定位置。void
ensureCapacity(int minimumCapacity)
确保容量至少等于规定的最小值。
void
getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
字符从该序列复制到目标字符数组
dst
。int
indexOf(String str)
返回指定子字符串第一次出现的字符串内的索引。
int
indexOf(String str, int fromIndex)
返回指定子串的第一次出现的字符串中的索引,从指定的索引开始。
StringBuffer
insert(int offset, boolean b)
在此序列中插入
boolean
参数的字符串表示形式。StringBuffer
insert(int offset, char c)
在此序列中插入
char
参数的字符串表示形式。StringBuffer
insert(int offset, char[] str)
在此序列中插入
char
数组参数的字符串表示形式。StringBuffer
insert(int index, char[] str, int offset, int len)
在此序列中插入
str
数组参数的子阵列的字符串表示形式。StringBuffer
insert(int dstOffset, CharSequence s)
将指定的
CharSequence
这个序列。StringBuffer
insert(int dstOffset, CharSequence s, int start, int end)
将指定的子序列
CharSequence
这个序列。StringBuffer
insert(int offset, double d)
在此序列中插入
double
参数的字符串表示形式。StringBuffer
insert(int offset, float f)
在此序列中插入
float
参数的字符串表示形式。StringBuffer
insert(int offset, int i)
将第二个
int
参数的字符串表示插入到此序列中。StringBuffer
insert(int offset, long l)
在此序列中插入
long
参数的字符串表示形式。StringBuffer
insert(int offset, Object obj)
将
Object
参数的字符串表示插入到此字符序列中。StringBuffer
insert(int offset, String str)
将字符串插入到此字符序列中。
int
lastIndexOf(String str)
返回指定子字符串最右边出现的字符串内的索引。
int
lastIndexOf(String str, int fromIndex)
返回指定子字符串最后一次出现的字符串中的索引。
int
length()
返回长度(字符数)。
int
offsetByCodePoints(int index, int codePointOffset)
返回此序列中与
index
(codePointOffset
代码点偏移的索引。StringBuffer
replace(int start, int end, String str)
用指定的String中的字符替换此序列的子字符串中的
String
。StringBuffer
reverse()
导致该字符序列被序列的相反代替。
void
setCharAt(int index, char ch)
指定索引处的字符设置为
ch
。void
setLength(int newLength)
设置字符序列的长度。
CharSequence
subSequence(int start, int end)
返回一个新的字符序列,该序列是该序列的子序列。
String
substring(int start)
返回一个新的
String
,其中包含此字符序列中当前包含的字符的子序列。String
substring(int start, int end)
返回一个新的
String
,其中包含此序列中当前包含的字符的子序列。String
toString()
返回表示此顺序中的数据的字符串。
void
trimToSize()
尝试减少用于字符序列的存储。
4. StringBuilder
- 一个可变的字符序列。 此类提供与
StringBuffer
的API,但不保证同步。 此类设计用作简易替换为StringBuffer
在正在使用由单个线程字符串缓冲区的地方(如通常是这种情况)。 在可能的情况下,建议使用这个类别优先于StringBuffer
,因为它在大多数实现中将更快。- StringBuilder的主要
StringBuilder
是append
和insert
方法,它们是重载的,以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符附加或插入字符串构建器。append
方法始终在构建器的末尾添加这些字符;insert
方法将insert
添加到指定点。- 例如,如果
z
引用当前内容为“start
”的字符串构建器对象,那么方法调用z.append("le")
将导致字符串构建器包含“startle
”,而z.insert(4, "le")
会将字符串构建器更改为包含“starlet
”。- 一般情况下,如果某人是指的一个实例
StringBuilder
,则sb.append(x)
具有相同的效果sb.insert(sb.length(), x)
。- 每个字符串构建器都有一个容量。 只要字符串构建器中包含的字符序列的长度不超过容量,则不需要分配新的内部缓冲区。 如果内部缓冲区溢出,则会自动变大。
- StringBuilder的
StringBuilder
不能安全使用多线程。 如果需要同步, 那么建议使用StringBuffer (推荐单线程使用,效率最高)。- 除非另有说明,否则将
null
参数传递给null
中的构造函数或方法将导致抛出NullPointerException 。
5 String,StringBuffer,StringBuilder比较
String | StringBuffer | StringBuilder | |
---|---|---|---|
字符序列可变性 | F | T | T |
复用率 | 高 | 低 | 低 |
效率 | 最低 | 中等 | 最高 |
线程安全 | -- | 多线程 | 不同步 |
方法 | String自己的方法 | StringBuffer和StringBuilder方法一样 | |
适合使用场景 | 多对象引用,且修改次数少 | 1.大量修改操作 2.多线程 | 1.大量修改操作 2.单线程 |
复用率:指常量池有相同内容的字符串可以不用再开辟常量池,直接指向该字符串