【详识JAVA语言】String类2

本文解释了Java中String对象的不可变性原理,介绍了StringBuffer和StringBuilder的区别,强调了在需要修改字符串时应使用StringBuilder以提高效率,并通过面试题的形式展示了两者之间的关键点和使用场景。
摘要由CSDN通过智能技术生成

常用方法

字符串的不可变性

String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:

1. String类在设计时就是不可改变的,String类实现描述中已经说明了

以下来自JDK1.8中String类的部分实现:

String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:

1. String类被final修饰,表明该类不能被继承

2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中 的内容可以修改。

2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象 

比如replace方法:

【纠正】网上有些人说:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。 这种说法是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。

final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内 容是可以修改的。 

public static void main(String[] args) {

final int array[] = {1,2,3,4,5};

array[0] = 100;

System.out.println(Arrays.toString(array)); 

// array = new int[]{4,5,6}; 

// 编译报错:Error:(19, 9) java: 无法为最终变量array分配值

}

 

为什么 String 要设计成不可变的?(不可变对象的好处是什么?) (选学)

1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.

2. 不可变对象是线程安全的.

3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.

那如果想要修改字符串中内容,该如何操作呢?

字符串修改

注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率 非常低下。

public static void main(String[] args) {

String s = "hello";

s += " world";

System.out.println(s); // 输出:hello world

}

但是这种方式不推荐使用,因为其效率非常低,中间创建了好多临时对象。

public static void main(String[] args) {

long start = System.currentTimeMillis(); 

String s = ""; 

for(int i = 0; i < 10000; ++i){ 

s += i; 

} 

long end = System.currentTimeMillis(); 

System.out.println(end - start);

start = System.currentTimeMillis(); 

StringBuffer sbf = new StringBuffer(""); 

for(int i = 0; i < 10000; ++i){ 

sbf.append(i); 

} end = System.currentTimeMillis(); 

System.out.println(end - start);

start = System.currentTimeMillis(); 

StringBuilder sbd = new StringBuilder(); 

for(int i = 0; i < 10000; ++i){ 

sbd.append(i); 

} 

end = System.currentTimeMillis(); 

System.out.println(end - start);

}

可以看待在对String类进行修改时,效率是非常慢的,因此:尽量避免对String的直接需要,如果要修改建议尽量 使用StringBuffer或者StringBuilder。

b. 借助StringBuffer 和 StringBuilder

 StringBuilder和StringBuffer

StringBuilder的介绍

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大 部分功能是相同的,这里介绍 StringBuilder常用的一些方法。

方法

说明

StringBuff append(String str)

在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量

char charAt(int index)

获取index位置的字符

int length()

获取字符串的长度

int capacity()

获取底层保存字符串空间总的大小

void ensureCapacity(intmininmumCapacity)

扩容

void setCharAt(int index, char ch)

将index位置的字符设置为ch

int indexOf(String str)

返回str第一次出现的位置

int indexOf(String str, int fromIndex)

从fromIndex位置开始查找str第一次出现的位置

int lastIndexOf(String str)

返回最后一次出现str的位置

int lastIndexOf(String str, intfromIndex)

从fromIndex位置开始找str最后一次出现的位置

StringBuff insert(int offset, String str)

在offset位置插入:八种基类类型 & String类型 & Object类型数据

StringBuffer deleteCharAt(int index)

删除index位置字符

StringBuffer delete(int start, int end)

删除[start, end)区间内的字符

StringBuffer replace(int start, int end,String str)

将[start, end)位置的字符替换为str

String substring(int start)

从start开始一直到末尾的字符以String的方式返回

String substring(int start,int end)

将[start, end)范围内的字符以String的方式返回

StringBuffer reverse()

反转字符串

String toString()

将所有字符按照String的方式返回

public static void main(String[] args) {

StringBuilder sb1 = new StringBuilder("hello"); 

StringBuilder sb2 = sb1;

// 追加:即尾插-->字符、字符串、整形数字 

sb1.append(' ');  // hello 

sb1.append("world");  // hello world 

sb1.append(123);  // hello world123 

System.out.println(sb1); // hello world123 

System.out.println(sb1 == sb2); // true 

System.out.println(sb1.charAt(0)); // 获取0号位上的字符 h 

System.out.println(sb1.length()); // 获取字符串的有效长度14 

System.out.println(sb1.capacity()); // 获取底层数组的总大小 

sb1.setCharAt(0, 'H'); // 设置任意位置的字符 Hello world123 

sb1.insert(0, "Hello world!!!"); // Hello world!!!Hello world123

System.out.println(sb1); 

System.out.println(sb1.indexOf("Hello")); // 获取Hello第一次出现的位置 

System.out.println(sb1.lastIndexOf("hello")); // 获取hello最后一次出现的位置 

sb1.deleteCharAt(0); // 删除首字符 

sb1.delete(0,5); // 删除[0, 5)范围内的字符

String str = sb1.substring(0, 5); 

System.out.println(str); 

sb1.reverse(); // 字符串逆转 

str = sb1.toString(); // 将StringBuffer以String的方式返回 

System.out.println(str);

// 截取[0, 5)区间中的字符以String的方式返回

}

从上述例子可以看出:String和StringBuilder最大的区别在于String的内容无法修改而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。

注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:

String变为StringBuilder: 利用StringBuilder的构造方法或append()方法

StringBuilder变为String: 调用toString()方法。

 面试题

1. String、StringBuffer、StringBuilder的区别

String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.

StringBuffer与StringBuilder大部分功能是相似的

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

2. 以下总共创建了多少个String对象【前提不考虑常量池之前是否存在】

String str = new String("ab"); // 会创建多少个对象 
String str = new String("a") + new String("b"); // 会创建多少个对象

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CaojunjiaOnly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值