一篇讲清楚String、StringBuffer和StringBuild

一、String篇

(jdk文档原文)String类代表字符串。 Java程序中的所有字符串文字(例如 "abc" )都被实现为此类的实例。

说人话就是:String是用来保存字符串的,比如:”我好帅啊”、”123456″、”hello”这些都是字符串,而区分是否为字符串的标志就是这对双引号:””。

  • String是一个final类,代表不可变的字符序列。
  • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
  • String对象的字符内容是存储在一个字符数组value[]中的。

字符串不变; 它们的值在创建后不能被更改。 字符串缓冲区支持可变字符串。 因为String对象是不可变的,它们可以被共享。 例如:

String str = "abc";
​

相当于:

char data[] = {'a', 'b', 'c'};
  String str = new String(data);
​

以下是一些如何使用字符串的示例:

System.out.println("abc");
  String cde = "cde";
  System.out.println("abc" + cde);
  String c = "abc".substring(2,3);
  String d = cde.substring(1, 2);

我们看看源码,发现value这个字符数组被final修饰了,怪不得String是不可变的。

1)Serializable:

*

public interface Serializable

类的序列化由实现java.io.Serializable接口的类启用。不实现此接口的类将不会使任何状态序列化或反序列化。可序列化类的所有子类型都是可序列化的。序列化接口没有方法或字段,仅用于标识可串行化的语义。 为了允许序列化不可序列化的子类型,子类型可能承担保存和恢复超类型的公共,受保护和(如果可访问)包字段的状态的责任。 子类型可以承担此责任,只有当它扩展的类具有可访问的无参数构造函数来初始化类的状态。 如果不是这样,声明一个类Serializable是一个错误。 错误将在运行时检测到。 在反序列化期间,非可序列化类的字段将使用该类的public或protected no-arg构造函数进行初始化。 对于可序列化的子类,必须可以访问no-arg构造函数。 可序列化子类的字段将从流中恢复。 当遍历图形时,可能会遇到不支持Serializable接口的对象。 在这种情况下,将抛出NotSerializableException,并将标识不可序列化对象的类

2)Comparable

*

public interface Comparable

该接口对实现它的每个类的对象强加一个整体排序。这个排序被称为类的 自然排序 ,类的 compareTo方法被称为其 自然比较方法Collections.sort (和Arrays.sort )可以自动对实现此接口的对象进行列表(和数组)排序。 实现该接口的对象,可以使用如在键sorted map或作为在元件sorted set ,而不需要指定一个comparator 。 一类 C的自然顺序被说成是 _与equals一致_当且仅当 e1.compareTo(e2) == 0对每一个 e1Ce2相同的布尔值 e1.equals(e2)。 请注意, null不是任何类的实例, e.compareTo(null)应该抛出一个 NullPointerException即使 e.equals(null)返回 false 。 强烈建议(尽管不需要)自然排序与等于一致。 这是因为,当没有显式比较器的排序集(和排序映射)与其自然排序与equals不一致的元素(或键)一起使用时会”奇怪地”。 特别地,这种排序集合(或排序映射)违反了根据 equals方法定义的集合(或映射)的一般合同。

3)CharSequence:

*

public interface CharSequence

CharSequencechar值的可读序列。该界面提供统一的,只读访问许多不同类型的 char序列。 char值代表 _基本多语言平面(BMP)_或代理中的一个字符。详见Unicode Character Representation 。 此界面不会完善equalshashCode方法的一般合同。 因此,比较两个对象实现 CharSequence其结果是,在一般情况下,不确定的。 每个对象可以由不同的类实现,并且不能保证每个类都能够测试其实例以与另一个类相同。 因此,使用任意的 CharSequence实例作为集合中的元素或映射中的键是不合适的

方式一、直接赋值:String s = “归海”;

这种方式它首先会先从常量池查看是否有”归海” 这个数据空间,如果有就直接指向,如果没有就创建一个”归海”这个数据空间然后指向它。注意s最终指向的是常量池的空间地址。

方式二、调用构造器 String s1= new String(“归海”);

这种方式则是先在堆中创建空间,里面维护了value属性,指向常量池的”归海”空间。如果常量池中没有”归海”,则重新创建,如果有就直接通过value指向。注意这里最终指向的是堆中的空间地址。

经过刚才简单的介绍你应该对String有一点印象了,ok话不多说来几道练习题:

例题一:

String a = “abc’;

String b = “abc”;

System.out.println(a == b) ; //true/fales

System.out.println(a.equals(b));//true/fales

例题二:

String a = new String(“abc”);

String b = new String(“abc”);

System.out.println(a == b) ; //true/fales

System.out.println(a.equals(b));//true/fales

例题三:

String a = “归海’;

String b = new String(“归海”);

System.out.println(a == b) ; //true/fales

System.out.println(a.equals(b));//true/fales

例题四:

Person p1 = new Person();

p1.name = “归海”;

Person p2 = new Person() ;

p2.name = “归海”;

System.out.println(p1.name.equals(p2.name));//true/fales

System.out.println(p1.name == p2.name) ; //true/fales

System.out.println(p1.name == “归海”) ; //true/fales

来说一下答案吧。

(1)T, T;

(2)F, T;

(3)F, T;

(4)T, T, T;

6、String 类常用方法

序号方法描述 1

7 [static String copyValueOf(char

8 [static String copyValueOf(char

10

11

12 [byte

13 [byte

14 [void getChars(int srcBegin, int srcEnd, char

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32 [String

33 [String

34

35

36

37

38

39 [char

40

41

42

43

44

45

46

不过发现没String类的效率有点低啊!这是String类因为每次更新内容都要重新开辟空间,为此java设计者还提供了StringBuilder和SreingBuffer类来增强String功能和效率。

二、StringBuffer篇

1)它也是一个元老级别的类了从jdk1.0的时候就有了

2)StringBuffer是一个可变的字符序列,可以对字符内容进行更改。

3)StringBuffer的很多方法也String相同,但是StringBuffer是可变长度的。

4)StringBuffer是一个容器。

2)字符缓冲可以安全的被多个线程使用。前提是这些方法必须进行同步。

3)每个字符串缓冲区都有一个容量。 只要字符串缓冲区中包含的字符序列的长度不超过容量,就不必分配新的内部缓冲区数组。 如果内部缓冲区溢出,则会自动变大

private transient char[] toStringCache; 这是StringBuffer可以更改的原因。

StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器:

  • StringBuffer():初始容量为16的字符串缓冲区
  • StringBuffer(int size):构造指定容量的字符串缓冲区
  • StringBuffer(String str):将内容初始化为指定字符串内容

1)Appendable:

*

public interface Appendable

可附加 char序列和值的对象。 Appendable接口必须由其实例旨在从Formatter接收格式化输出的任何类实现 。 要附加的字符应为Unicode Character Representation中描述的有效Unicode字符。 请注意,补充字符可以由多个16位 char值组成。 对于多线程访问,附加功能不一定是安全的。 线程安全是扩展和实现这个接口的类的责任。 由于此接口可能由具有不同样式的错误处理的现有类实现,因此不能保证将错误传播到调用者。

2)AbstractStringBuilder:首先这是一个类

:java.lang包中

: abstract class

implements Appendable, CharSequence AbstractStringBuilder 类有abstract 修饰,可知它不能被实例化。AbstractStringBuilder 类有两个子类:StringBuilder和StringBuffer。

序号方法描述 1 public StringBuffer append(String s) 将指定的字符串追加到此字符序列。 2 public StringBuffer reverse() 将此字符序列用其反转形式取代。 3 public delete(int start, int end) 移除此序列的子字符串中的字符。 4 public insert(int offset, int i) 将

参数的字符串表示形式插入此序列中。 5 replace(int start, int end, String str) 使用给定

中的字符替换此序列的子字符串中的字符

1)String用于字符串操作,属于不可变类,而StringBuffer也是用于字符串操作,不同之处是StringBuffer属于可变类。

2) String是不可变类,也就是说,String对象一旦被创建,其值将不能被改变,而StringBuffer是可变类,当对象被创建后,仍然可以对其值进行修改。

3)String类每次更新实际上是更改地址,因此它的效率低。

4)StringBuffer类每次更新是更新内容,不用更新地址,因此它的效率高。

三、StringBuilder篇

1)一个可变的的字符序列。提供了和SteingBuffer兼容的API。

2)StringBuilder是线程不安全的,此类设计用作简易替换为 StringBuffer在正在使用由单个线程字符串缓冲区的地方。

3)StringBuilder的主要 StringBuilderappendinsert方法,它们是重载的,以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符附加或插入字符串构建器。

4)它的速度比StringBuffer快毕竟线程不安全换来的。

我们会发现和StringBuffer一模一样,所以它们的API兼容也是正常。

源码也没什么说的,因为我也不会。

对比String、StringBuffer、StringBuilder

  • String(JDK1.0):不可变字符序列 ,效率低但是复用率高。
  • StringBuffer(JDK1.0):可变字符序列、效率较高、线程安全。
  • StringBuilder(JDK 5.0):可变字符序列、效率最高、线程不安全

注意:作为参数传递的话,方法内部String不会改变其值,StringBuffer和StringBuilder 会改变其值。

代码例子

这个是 i < 180000次的结果

可以发现如果次数不是很大StringBuffer和StringBuilder的差距还是可以的。次数越大差距越大。

四、总结:

String、StringBuffer、StringBuilder的选择:

1、如果字符串中存在大量的修改操作,可以选择StrinBuffer和StringBuilder其中之一。

2、如果字符串中存在大量的修改操作而且在单线程的情况下,使用StringBuilder。

3、如果字符串中存在大量的修改操作而且在多线程的情况下,使用StringBuffer。

4、如果字符串修改很少、被多个对象引用,使用String。这个在配置信息的时候应用广泛。

Original: https://www.cnblogs.com/guihai/p/16213496.html
Author: 归~海
Title: 一篇讲清楚String、StringBuffer和StringBuild

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/608832/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 搭建 RabbitMQ Server 高可用集群

    阅读目录: 准备工作 搭建 RabbitMQ Server 单机版 RabbitMQ Server 高可用集群相关概念 搭建 RabbitMQ Server 高可用集群 *搭建 H…

    Java 2023年5月30日
    075
  • windows media play javascript 全屏 单击事件

    上面代码放在HTML页面中, 倒数三行的设置,是对应如果你要做JAVASCRIPT里是否要获取到,0是false,只是不明白为什么-1是true, 然后在HTML里面加入 docu…

    Java 2023年6月14日
    060
  • Mysql 计算地址经纬度距离实时位置

    前言 最近在做项目时候,遇到一个这样子的需求, 点到卡包里面卡券使用使用,需要展示卡券使用附近门店, 思路 数据库地址表设计 通用的区域街道地址表 tz_sys_area 字段名称…

    Java 2023年6月13日
    081
  • MyBatis:log4j配置

    LOG_DIR=D:/logs/mybatis log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appe…

    Java 2023年5月30日
    065
  • SpringBoot连接MySQL配置(yml)?

    SpringBoot连接MySQL 需要导入的依赖 1. MySQL 8 yaml配置: undefined 2. MySQL 5 yaml配置: spring Original:…

    Java 2023年6月9日
    058
  • Day1 使用MarkDown

    二级标题 三级标题 Hello,world Hello,world Hello,world Hello,world java 分割线 超链接 A B VC https://imag…

    Java 2023年6月5日
    077
  • 关系数据库元数据处理类(三) 创建查询元数据代理类

    1 public class MetadataManager : IMetadata 2 { 3 private readonly IMetadata _metadata; 4 5…

    Java 2023年6月5日
    071
  • Java面试题(五)–Rabbits

    1、什么是MyBatis? 1、Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建…

    Java 2023年6月9日
    076
  • Dubbo面试大纲

    本篇文章不是进行详细的Dubbo实现以及原理分析的文章,适用于用过Dubbo,对Dubbo有一定了解准备面试的小伙伴阅读。下面列的一些点,如果能在面试时候说到,那面试官肯定觉得不错…

    Java 2023年6月7日
    077
  • 【翻译】Spring Security-如何解决WebSecurityConfigurerAdapter类已被弃用的问题?

    原文发表日期:2022年6月1日 在这篇短文中,我想分享如何在使用Spring Security的Spring应用中避免” WebSecurityConfigurerA…

    Java 2023年6月6日
    053
  • JDK 自带的观察者模式源码分析以及和自定义实现的取舍

    setChanged 这个开关的作用——可以借鉴思想 1、使得主题具备了很大的伸缩性 假如没有 setChanged,那么一旦主题的状态变了,就不得不立即通知订阅者,这不是很合理,…

    Java 2023年5月30日
    067
  • Java8新特性Optional

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月7日
    067
  • 【笔试】1、强迫卖家

    小明是个强迫症卖家,有10000台设备,卖的均价要求最接近D元,输出卖出的台数N,总售价M 输入 0首先想得是暴力解答然后是二分查找,寻找卖出多少台才符合要求,但是一直找不到符合要…

    Java 2023年6月5日
    075
  • zookeeper集群

    环境: 拥有三台服务器,假设三台服务器的Ip地址为 172.18.19.143,172.18.19.15,172.18.19.129 开放三台服务器的2287,3387端口 集群搭…

    Java 2023年6月8日
    074
  • 爬虫爬取网页基本的代码

    import urllib.request,urllib.parse strs = \ ”’blackside_state=0; buvid4=93AB1303-E725-8C6…

    Java 2023年6月5日
    0170
  • JMeter While循环控制器应用之遍历获取文件参数

    作者:授客微信/QQ:1033553122全国软件测试QQ交流群:7156436Git地址:https://gitee.com/ishouke友情提示:限于时间仓促,文中可能存在错…

    Java 2023年6月16日
    057
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球