字符串常量:String、StringBuilder和 StringBuffer 的区别?

字符串常量:String、StringBuilder和 StringBuffer 的区别?,第1张

字符串常量:String、StringBuilder和 StringBuffer 的区别? String 字符串
String 字符串是引用类型,底层用 char 数组实现的。

String 字符串的特点:

        1.字符串不可变,它们的值在创建后不能被更改。

        2.虽然String 的值是不可变的,但是可以被共享 字符串效果上相当于字符数组( char[] ),但是底层原理是字节数组( byte[] )。

String 字符串解析:

        1.通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,即使内容相同,但地址值不同。

        2.以“”方式给出的字符串,JVM会将其存放在 字符串常量池 中维护。

        3.且若多个“”方式给出的字符序列(顺序及大小写)相同,JVM只会建立一个String 对象。

为什么 String 字符串 不适用于 大量 字符串 拼接 *** 作?

String的值是不可变的,这就导致每次对String的 *** 作都会生成新的String对象,对内存空间的极大浪费。

String 字符串的 + *** 作(字符串 拼接 *** 作)其本质是创建了 StringBuilder 对象进行 append()  *** 作,然后将拼接后的 StringBuilder 对象用 toString() 方法处理成 String 对象。

在 Java 中无论使用何种方式进行字符串连接,实际上都使用的是 StringBuilder。

我们知道,在Java中有两种创建字符串对象的方式:

    采用字面值的方式赋值。采用new关键字 新建一个字符串对象。
String str = new String("abc")创建了几个对象?
创建2个对象。 第一个对象是”abc”字符串 存储 在字符串常量池中; 第二个对象在JAVA Heap堆 中 new 的 String 对象
String str = "a" + "b" + "c" 创建了几个对象?

创建1个对象。

因为 赋值符号右边的"a"、"b"、"c"都是常量

String str = new String("a") + new String("b")创建了几个对象?

创建6个对象。

        对象1:new StringBuilder()

        对象2:new String("a")

        对象3:常量池的 a

        对象4:new String("b")

        对象5:常量池的 b

        对象6:toString中会创建一个 new String("ab")

String str= "abc";
final String finalStr = "abc";//final修饰的是常量

String str1 = "abc01";    
        
String str2 = "abc" + "01";    
    
String str3 = str + "01";    
    
String str4 = finalStr + "01";   
 
String str5 = new String("abc01").intern();    


System.out.println(str1 == str2);    // true
System.out.println(str1 == str3);    // false
System.out.println(str1 == str4);    // true   //final修饰的是常量
System.out.println(str1 == str5);    // true
String 、StringBuilder 和 StringBuffer 的区别
1)、可变不可变 String:字符串常量,在修改时不会改变自身;若修改,等于重新生成新的字符串对象。 StringBuffer:字符串变量,在修改时会改变对象自身,每次 *** 作都是对 StringBuffer 对象本身进行修改,不是生成新的对象; 使用场景:对字符串经常改变情况下,主要方法:append(),insert()等。 2)、线程是否安全 String:对象定义后不可变,线程安全。 StringBuffer:是线程安全的(对调用方法加入synchronized同步锁),执行效率较慢,适用于多线程下 *** 作字符串缓冲区大量数据。 StringBuilder:是线程不安全的,StringBuilder 效率高于 StringBuffer,适用于单线程下 *** 作字符串缓冲区大量数据。 3)、共同点 StringBuilder 与 StringBuffer 有公共父类 AbstractStringBuilder(抽象类)。 StringBuilder、StringBuffer 的方法都会调用 AbstractStringBuilder 中的公共方法,只是StringBuffer 会在方法上加 synchronized 关键字,进行同步。 最后,如果程序不是多线程的,那么使用 StringBuilder 效率高于 StringBuffer。
String 不可变字符串线程安全每次new 都是生成新的String对象不适用于 大量 字符串 拼接 *** 作,影响内存性能 StringBuffer 可变字符串线程安全StringBuffer 执行效率慢适用于多线程下 *** 作字符串缓冲区大量数据 StringBuilder 可变字符串线程不安全StringBuilder 执行效率高适用于单线程下 *** 作字符串缓冲区大量数据

常量

用final修饰的成员变量表示常量,值一旦给定就无法改变!

final修饰的变量分别表示三种类型的常量:静态变量、实例变量 和 局部变量。

Java中的常量池,实际上分为两种形态:静态常量池 和 运行时常量池。

    1)静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。

    2)运行时常量池,则是JVM虚拟机在完成类装载 *** 作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

常量池(Constant Pool)
常量池,也叫 Class 常量池(常量池==Class常量池,Class Constant Pool)。Java文件被编译成 Class文件,Class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项就是常量池,每个class文件都有一个class常量池。常量池是当Class文件被Java虚拟机加载进来后存放在方法区 各种 字面量 (Literal)和 符号引用(SymbolicReferences)。

字面量 包括:1.文本字符串 2.八种基本类型的值 3.被声明为final的常量等;

符号引用 包括:1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。

运行时常量池(Runtime Constant Pool)

运行时常量池是方法区的一部分。运行时常量池是当Class文件被加载到内存后,Java虚拟机会 将Class文件常量池里的内容转移到运行时常量池里(运行时常量池也是每个类都有一个)。运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中

字符串常量池(String Constant Pool)

字符串常量池又称为:字符串池,全局字符串池,英文也叫String Constant Pool。

字符串常量池是全局的,JVM中独此一份,因此也称为全局字符串常量池。

String的String Pool是一个固定大小的Hashtable,默认值大小长度是1009。

在工作中,String类是我们使用频率非常高的一种对象类型。JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存空间,这就是我们今天要讨论的核心:字符串常量池。字符串常量池由String类私有的维护

class常量池 是在编译的时候每个class都有的. 在编译阶段,存放的是常量的 符号引用 。       [在class文件中]


字符串常量池 在每个VM中只有一份,存放的是字符串常量的 引用值 。  [在堆中]              


运行时常量池 是在类加载完成之后,将每个class常量池 中的符号引用值转存到 运行时常量池 中,也就是说,每个class都有一个 运行时常量池 ,类在 解析阶段 ,将 符号引用 替换成 直接引用 ,与 字符串常量池 中的引用值保持一致。[在方法区]  

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5706754.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存