CSDN话题挑战赛第1期
活动详情地址:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f
参赛话题:Java学习记录
话题描述:每个人学习的路线不同,学习的方式视频教学和跟的老师不同,一个知识点会多种不同的讲解之法,下面这篇文章记录了我的学习记录并且我不懂或漏掉的知识点又去找其他书籍进行了补充,我觉得依旧不是最完整的,等我遇到了还会对这部分知识点进行补充。
目录
一、前言
二、字符串的注意事项
1、细节部分
2、两种方式创建String 对象
三、StringBuffer 类
1、细节部分
2、StringBuffer 和 String 之间相互转换
四、StringBuilder 类
细节部分
五、 String类、StringBuffer类 和 StringBuilder类比较
Ⅰ、三者的区别
Ⅱ 三者的效率及使用原则
一、前言
- 学习概述:这篇文章主要介绍Java的字符串类型,字符串的常用方法我在前面的文章已经介绍过,这一篇主要介绍它的细节,平时使用字符串时需要注意的地和易错易混的地方,其中有比较长用的StringBuffer类和StringBuilder类的细节详解。
- 学习目标:学习了这篇文章之后,要掌握字符串的常见易错的地方;StringBuffer类和StringBuilder类的细节及StringBuffer类与字符串之间的转换;字符串、StringBuffer类和StringBuilder类三者的比较,什么时候用哪一个类必须要掌握。
1、细节部分
▷ String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低,(private final char value[];)。
▷ 字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节
▷ String 类有很多构造器 ---> 构造器的重载
▷ String 类实现了接口 Serializable(String 可以串行化:可以在网络传输) 和 接口 Comparable (String 对象可以比较大小)
▷ String 是 final 类,不能被其他的类继承,同时代表不可变字符串序列,一个字符串对象一旦被分配,其内容是不可变的
▷ String 有属性 private final char value[]; 用于存放字符串的内容。value 是一个 final 类型, 不可以修改:即 value 不能指向新的地址,但是单个字符内容是可以变化
▷ 注意: 一个空字符串并不是说它的值等于null (空值),空字符串和null(空值)是两个概念。空字符事是由空的 " " 符号定义的,它是实例化之后的字将串对象,但是不包含任何字符。
2、两种方式创建String 对象
方式一:直接赋值 String s1 = "hello";
解释:先从常量池查看是否有"hello"数据空间,如果有,直接指向:如果没有则重新创建,然后指向。s1最终指向的是常量池的空间地址
..................................................................................................................................................
方式二: 调用构造器 String s2 = new String("hello");
解释:先在堆中创建空间,里面维护了value属性,指向常量池的hello空间。如果常量池没有"hello",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
图示:
1、细节部分
▶ StringBuffer 的直接父类 是 AbstractStringBuilder
▶ StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化
▶ 在父类中 AbstractStringBuilder 有属性 char[] value,不是 final 类,该 value 数组存放字符串内容,字符序列存放在堆中的。
▶ StringBuffer 是一个 final 类,不能被继承
▶ StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer 的更新实际上是可以只更新内容的,不用每次更新地址,效率较高,(char[ ] value; --->这个放在堆中)。
2、StringBuffer 和 String 之间相互转换
1、String —> StringBuffer :
String str = "hello tom"; //方式一 :使用构造器 StringBuffer str1 = new StringBuffer(str); //注意: 返回的str1才是 StringBuffer 对象,对 str 本身没有影响(不变) //方式二 :使用的是 append 方法 StringBuffer str2 = new StringBuffer(); str2 = str2.append(str);
2、StringBuffer ---> String :
StringBuffer str = new StringBuffer("jack"); //方式一 : 使用 StringBuffer 提供的 toString 方法 String str1 = str.toString(); //方式二 : 使用构造器来搞定 String str2 = new String(str);
3、StringBuffer 类构造器
构造方法 解释 StringBuffer() 构造个其中不带字符的字符串缓冲区,其初始容量为16个字符。 StringBuffer(CharSequence seq) public java.lang.StringBuilder(CharSequencese)构造一个字符串缓冲区,它包含与指定的Char Sequence相同的字符。 StringBuffer(int capacity) //capacity[容量] 构造一个不带字符, 但具有指定初始容量的字符串缓冲区,即对 char[]大小进行指定 StringBuffer(String str) 构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
细节部分
▶ StringBuilder 的直接父类 是 AbstractStringBuilder 类
▶ StringBuilder 实现了 Serializable, 即 StringBuilder 的对象可以串行化
▶ 在父类中 AbstractStringBuilder 有属性 char[] value,不是 final 类,该 value 数组存放 字符串内容,字符序列存放在堆中的。
▶ StringBuilder 是一个 final 类,不能被继承
▶ 因为 StringBuilder 字符内容是存在 char[] value, 所以在变化(增加/删除) 不用每次都更换地址(即不是每次创建新对象), 所以效率高于 String 类
▶ StringBuilder 的方法,没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用 StringBuilder
Ⅰ、三者的区别
1、String是不可变的,StringBuffer和StringBuilder都是可变的。
2、String不可变,可视为常量,所以线程安全; StringBuffer使用时加了同步锁,所以是线程安全的; StringBuilder 没加锁,所以不是线程安全的。
3、操作少量数据用String;单线程字符串缓冲区下操作大量数据用StringBuilder;多线程字符串缓冲区下操作大量数据用StringBuffer。简化比较:
▷ String : 不可变字符序列,效率低,但是复用率高。
▷ StringBuffer : 可变字符序列、效率较高(增删)、线程安全
▷ StringBuilder : 可变字符序列、效率最高(增删)、线程不安全注意:
▷ StringBuilder和StringBuffer非常类似,均代表可变的字符序列,而且方法也一样
▷ String注意事项:
string s="a"; //创建了一个字符串
s += "b";//实际上原来的"a"字符串对象已经丢弃了。现在又产生了一个字符串s+"b" (也就是"ab")。如果多次执行这种改变字符串内容的操作,会导致大量副本字符串对象残留在内存中,降低效率,浪费空间。如果这样的操作放到循环中,会极大影响程序的性能。所以如果我们要对字符串做大量修改,不要使用String 类。
Ⅱ 三者的效率及使用原则
效率:
StringBuilder 类 > StringBuffer 类 > String 类
使用原则:
1、如果字符串存在大量的修改操作,-般使用StringBuffer或StringBuilder
2、如果字符串存在大量的修改操作,并且在单线程的情况,使用StringBuilder
3、如果字符串存在大量的修改操作,并且在多线程的情况,使用StringBuffer
4、如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等
CSDN话题挑战赛第1期
活动详情地址:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f