String常量池和堆区介绍:String、StringBuilder与StringBuffer的区别?

网安智编 厦门萤点网络科技 2025-07-24 00:04 85 0
常量池和堆区 简单介绍 简单的来说: 类中使用 final 关键字修饰字符数组来保存字符串, final char value ,所以 对象是不可变的。 而 与 都继承自 r 类,在 r 中也是使用字符数组保存字符串 但是没有用...

常量池和堆区

简单介绍

简单的来说: 类中使用 final 关键字修饰字符数组来保存字符串, final char value ,所以 对象是不可变的。 而 与 都继承自 r 类,在 r 中也是使用字符数组保存字符串 但是没有用 final 关键字 修饰,所以这两种对象都是可变的。 与 的构造方法都是调用父类构造方法也就是 r 实现的。

r.java

线程安全性

中的对象是不可变的,也就可以理解为常量,线程安全。 r 是 与 的公共父类,定义了一些字符串的基本操作,如 、 、 、 等公共方法。 对方法加了同步锁或 者对调用的方法加了同步锁,所以是线程安全的。 并没有对方法进行加同步锁,所以 是非线程安全的。

性能

每次对 类型进行改变的时候,都会生成一个新的 对象,然后将指针指向新的 对象。 每次都会对 对象本身进行操作,而不是生成新的对象 并改变对象引用。相同情况下使用 相比使用 仅能获得 10%~15% 左 右的性能提升,但却要冒多线程不安全的风险。 对于三者使用的总结:

操作少量的数据: 适用 单线程操作字符串缓冲区下操作大量数据: 适用 多线程操作字符串缓冲区下操作大量数据: 适用 代码分析

image-20211116201042608


public class Str1 {
	public static void main(String[] args) {
		
		//直接引号赋值
		String str1="abc";
		String str2="abc";
		System.out.println(str1==str2);//true
		
		//通过new创建对象
		String str3="abc";
		String str4=new String("abc");
		System.out.println(str3==str4);//false
		
		String str5=new String("abc");
		String str6=new String("abc");

StringBuilder与StringBuffer线程安全性对比_string池_String常量池与堆区区别

System.out.println(str5==str6);//false } }

采用引号赋值创建一个字符串时,JVM首先会在常量池中找有没有这个对象,没有则在常量池中创建这个对象"abc",然后把字符串对象的引用地址返回给字符串常量str1有则不再创建新的对象,直接把字符串对象的引用地址返回给字符串常量str2因此.out.(str1==str2);//true输出为true 采用new创建对象,JVM则在堆区创建"abc"对象,然后将对象的地址返回赋给str4引用每一次new都会在堆区创建一个新的"abc"对象

	/*
		 * 首先在常量池创建一个"abcdef"的对象,并返回给str7
		 * "abc"+"def"会先实现拼接,然后再到常量池中找"abcdef"
		 * str7和str8都会指向同一个"abcdef"对象,两者的地址相同
		 */
		String str7="abcdef";
		String str8="abc"+"def";
		System.out.println(str7==str8);//true

        String s1="a";
        String s2=s1+"b";
		/*String s2=s1+"b";
		 * 等价于
		 * StringBuffer tempBuffer=new StringBuffer();
			tempBuffer.append("a");
			tempBuffer.append("b");
			String s2=tempBuffer.toString();
		*/
    	System.out.println(s1==s2);//false