【Java】String、StringBuffer、StringBuilder
2021/9/22 1:09:52
本文主要是介绍【Java】String、StringBuffer、StringBuilder,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
java.lang.String类
概述
String
:代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现
- String声明为final,不可被继承
- 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
- String实现了Serializable接口:表示字符串是支持序列化的。
- 实现了Comparable接口:表示String可以比较大小
- String内部定义了
private final char[] value
用于存储字符串数据 - 通过字面量的方式(区别于用
new String()
给字符串赋值),此时的字符串值声明在字符串常量池中)。 - 字符串常量池中是不会存储相同内容(使用String类的
equals()
比较)的字符串的。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0
String的不可变 性
- 当对字符串重新赋值时,需要重新指定内存区域赋值
- 当对现在的字符串进行连接操作时,也需要重新指定内存区域赋值
- 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
总结就是只要字符串值有更改,都需要重新指定内存区域赋值。若新值在内存区域已存在,则直接指向该区域,若没有则重新开辟空间
String对象的创建
建议去看API,以下展示集几种常用的
//字面量方式 String str = "hello"; //本质上this.value = new char[0]; String s1 = new String(); //this.value = s.value; String s2 = new String(String s); //this.value = Arrays.copyOf(value, value.length); String s3 = new String(char[] a); //从字符数组a的startIndex位置截取count个字符 String s4 = new String(char[] a,int startIndex,int count);
从上面代码可以看出String实例化主要有两种方式
- 方式一:通过字面量定义的方式
- 方式二:通过new + 构造器的方式
//通过字面量定义的方式:此时的s1和s2的数据声明在方法区中的字符串常量池中。 String s1 = "javaEE"; String s2 = "javaEE"; //通过new + 构造器的方式:此时的s3和s4保存的是地址值,指向堆空间中的数据。 String s3 = new String("javaEE"); String s4 = new String("javaEE"); System.out.println(s1 == s2);//true System.out.println(s1 == s3);//false System.out.println(s1 == s4);//false System.out.println(s3 == s4);//false
面试题
-
String s = new String("abc");方式创建对象,在内存中创建了几个对象?
答:两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc" -
String str1 = "abc" 与 String str2 = new String("abc");的区别?
-
字符串拼接方式赋值的对比
String s1 = "javaEE"; String s2 = "hadoop"; String s3 = "javaEEhadoop"; String s4 = "javaEE" + "hadoop"; String s5 = s1 + "hadoop"; String s6 = "javaEE" + s2; String s7 = s1 + s2; String s9 = s1 + s2; System.out.println(s3 == s4);//true System.out.println(s3 == s5);//false System.out.println(s3 == s6);//false System.out.println(s3 == s7);//false System.out.println(s5 == s6);//false System.out.println(s5 == s7);//false System.out.println(s6 == s7);//false System.out.println(s7 == s9);//false String s8 = s6.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop” System.out.println(s3 == s8);//true **************************** String s1 = "javaEEhadoop"; String s2 = "javaEE"; String s3 = s2 + "hadoop"; System.out.println(s1 == s3);//false final String s4 = "javaEE";//s4:常量 String s5 = s4 + "hadoop"; System.out.println(s1 == s5);//true
- 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
- 只要其中一个是变量,结果就在堆中,且不管变量名是否相同开辟的空间都不同。
- 如果拼接的结果调用intern()方法,返回值就在常量池中
- 若变量用final修饰就变成常量
- 下列程序运行结果
public class StringTest { String str = new String("good"); char[] ch = { 't', 'e', 's', 't' }; public void change(String str, char ch[]) { str = "test ok"; ch[0] = 'b'; } public static void main(String[] args) { StringTest ex = new StringTest(); ex.change(ex.str, ex.ch); System.out.print(ex.str); //good 不可变性 System.out.println(ex.ch); //best } }
StringBuffer、StringBuilder
StringBuffer
:可变的字符序列;线程安全的,效率低;底层使用char[]
存储StringBuilder
:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]
StringBuffer与StringBuilder的内存解析
//以StringBuffer为例: String str = new String();//char[] value = new char[0]; String str1 = new String("abc");//char[] value = new char[]{'a','b','c'}; StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组。 System.out.println(sb1.length());//0 sb1.append('a');//value[0] = 'a'; sb1.append('b');//value[1] = 'b'; StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16]; System.out.println(sb2.length()); //3
扩容问题
如果要添加的数据长度大于16,那就需要扩容底层的数组。默认情况下,扩容为原来容量的2倍 + 2,同时将原数组中的元素复制到新的数组中。
开发中建议指定长度:
StringBuffer(int capacity
) 或StringBuilder(int capacity)
三者的执行效率
从高到低排列:StringBuilder > StringBuffer > String
String、StringBuffer、StringBuilder三者的对比
abstract class AbstractStringBuilder implements Appendable, CharSequence { char[] value; //value没有final修饰,可以扩容 int count; //count记录有效字符的个数 AbstractStringBuilder() { } AbstractStringBuilder(int capacity) { value = new char[capacity]; }
- StringBuilder 和 StringBuffer可用方法一致
- StringBuilder 和 StringBuffer都继承于AbstractStringBuilder
- StringBuffer之所以是线程安全的,是因为方法用
synchronized
修饰- StringBuilder 和 StringBuffer 支持链式调用
StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器
StringBuffer() //初始容量为16的字符串缓冲区 StringBuffer(int size) //构造指定容量的字符串缓冲区 StringBuffer(String str) //将内容初始化为指定字符串内容
StringBuffer 和 StringBuilder的常用方法
StringBufferappend(xxx) //提供了很多的append()方法,用于进行字符串拼接 StringBufferdelete(int start,int end) //删除指定位置的内容 StringBufferreplace(intstart,intend,Stringstr) //把[start,end)位置替换为str StringBufferinsert(int offset,xxx) //在指定位置插入xxx StringBufferreverse() //把当前字符序列逆转
这篇关于【Java】String、StringBuffer、StringBuilder的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-11cursor试用出现:Too many free trial accounts used on this machine 的解决方法
- 2025-01-11百万架构师第十四课:源码分析:Spring 源码分析:深入分析IOC那些鲜为人知的细节|JavaGuide
- 2025-01-11不得不了解的高效AI办公工具API
- 2025-01-102025 蛇年,J 人直播带货内容审核团队必备的办公软件有哪 6 款?
- 2025-01-10高效运营背后的支柱:文档管理优化指南
- 2025-01-10年末压力山大?试试优化你的文档管理
- 2025-01-10跨部门协作中的进度追踪重要性解析
- 2025-01-10总结 JavaScript 中的变体函数调用方式
- 2025-01-10HR团队如何通过数据驱动提升管理效率?6个策略
- 2025-01-10WBS实战指南:如何一步步构建高效项目管理框架?