zoukankan      html  css  js  c++  java
  • Java中String、StringBuffer和StringBuilder的区别

    Java中String、StringBuffer和StringBuilder的区别

           在Java中String、StringBuffer和StringBuilder是处理字符串常用的类,三者都封装在java.lang包中,三者都被final修饰,所以不能被继承。所以主要从三者的可变性、性能和安全性讨论三者的不同:

    三者的结构:

    一、可变性

    1、String:String为字符串常量,即String对象创建后不能被修改,每次对字符串操作都会产生新的对象,旧的对象会被GC回收。使用字符数组保存字符串:private final char value[ ];

    (1)、以赋值方式创建时,会到Java方法空间的字符串常量池中寻找,如果没有则会创建一个并返回内存地址赋值给对象变量,如果有就返回字符串常量池中返回内存地址赋值给对象变量

    (2)、以new方式创建时,则直接在堆中开辟空间,返回地址赋值给对象变量,不会去字符串常量池中寻找。

    (3)、String对象的修改假象

    1 String str = “hello”;
    2 str=str + “world”;
    3 System.out.println(str);

     

    当我们执行上面上面代码是控制台输出:helloworld,String看似被修改了,其实这是个假象。整个执行过程是这样的:

    1. 执行String str = “hello”时,先创建一个str对象,在堆中开辟一个空间存放“hello”,并把内存地址赋值给str;
    2. 执行str = str + “world”时,先在堆内存中开辟新的空间存放“world”,然后再开辟新的内存空间存放str + “world”,即“hello world”,然后将“hello world”在堆中的内存地址返回赋值给str;
    3. System.out.println(str):输出。

     2、StringBuffer与StringBuilder:可改变的Unicode字符序列,两者的对象是变量,对变量进行操作就是直接对该对象进行更改,而不会再次创建和回收的操作。使用字符数组保存字符串:char[ ] value;

    (1)、创建时通过new初始化对象,通过对象调用相应方法;

    (2)、StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

    二、性能:StringBuilder > StringBuffer > String

    1、StringBulder:没有实现线程安全功能,操作时不需要加锁,所以性能较高;

    2、StringBuffer:实现了线程安全,在每次操作时都要判断锁,性能较StringBuilder慢;

    3、String:每次操作时都会创建一个新的对象,从而经历了创建新对象,销毁旧对象的过程,所以性能最慢。

    三、线程安全

    1、StringBulder:没有实现线程安全功能,不具备多线程安全,但是在单线程情景下,性能最高;

    2、StringBuffer:方法大都通过synchronized关键字修饰,实现了线程安全;

    3、String:对象是不可变,通过final关键字修饰为一个常量,所以是线程安全的。

    四、StringBuffer的初始化及扩容

    1、StringBuffer():初始容量可以容纳16个字符,当该对象存放的字符大于16时,实体的容量会自动扩容,

    2、StringBuffer(int size):可以指定该对象初始化容量为size长度的字符个数,当该对象存放的字符序列大于size时,实体的容量会自动扩容;

    3、StringBuffer(String s):可以指定该对象的初始容量为该s字符串的长度再加上16个字符,当该对象存放的字符序列大于初始容量时,实体的容量会自动扩容;

    StringBuffer对象可以通过length()方法获取实体中存放的字符序列长度,通过capacity()方法来获取当前实体的实际容量。

    扩容算法:
    1、使用append()方法在字符串后面追加东西的时候,如果长度超过了该字符串存储空间大小了就需要进行扩容:构建新的存储空间来存储更大的字符串,将旧的复制过去;
    2、再进行字符串append添加的时候,会先计算添加后字符串大小,传入一个方法:ensureCapacityInternal 这个方法进行是否扩容的判断,需要扩容就调用expandCapacity方法进行扩容;
    3、尝试将新容量扩为大小变成2倍+2   if 判断一下 容量如果不够,直接扩充到需要的容量大小。

    (五)、StringBuilder与StringBuffer的共同点

    1、都有一个公共的AbstractStringBulder抽象类;

    2、都会调用AbstractStringBuilder方法,如super.append(...),只是StringBuffer为了实现线程安全,会用关键字synchronized修饰

    3、都是final关键字修饰的类,不允许被继承。

    (六)、总结

    1、String:适用于字符串少量操作的情况;

    2、StringBuffer:适用于在多线程环境下字符串大量操作的情况;

    3、StringBuilder:适用于在单线程环境下字符串大量操作的情况。

     

    以上是我自己平时学习的一个小知识点,如果有错误的地方,欢迎大家批评指正,谢谢!!

  • 相关阅读:
    Meta标签详解
    Python: 什么是*args和**kwargs
    如何进行 WebSocket 协议的压测
    在Mac上使用Microsoft Remote Desktop
    报表测试方法与注意事项
    Linux服务部署Yapi项目(安装Node Mongdb Git Nginx等) Linux服务部署Yapi
    mac安装brew(亲测)
    Linux下查看系统配置
    iTerm--比Terminal(终端)更好用的命令行工具
    协方差矩阵
  • 原文地址:https://www.cnblogs.com/lingq/p/12723355.html
Copyright © 2011-2022 走看看