String类中的常量池分析

Java中的字符串常量池

Java中字符串对象创建有两种形式:
1 字面直接赋值形式,如 String str = "gja";
2 通过 new 构造对象的方法 String str = new String("gja");

上述两种创建方式在性能和内存上存在一定的差异.

原因就是:JVM为了减少字符串对象的重复创建,维护了一个特殊的内存,这段内存就是字符串常量池

工作原理分析:

当使用第一种直接赋值的方式创建字符串对象时,JVM首先对这个字面量进行检查,如果字符串常量池中存在相同的内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个对象的引用放入字符串常量池,并返回该引用.

内存模型如下:
在这里插入图片描述
第一种方式:直接赋值

String s1 = "gja";
//JVM检测这个字面量,这里我们认为没有内容为`gja`的对象存在。
//JVM通过字符串常量池查找不到内容为`gja`的字符串对象存在
//那么会创建这个字符串对象,然后将刚创建的对象的引用放入到字符串常量池中,并且将引用返回给变量s1。
String s2 = "gja";
//同样JVM还是要检测这个字面量,JVM通过查找字符串常量池,
//发现内容为”gja”字符串对象存在,于是将已经存在的字符串对象的引用返回给变量s2。
//注意这里不会重新创建新的字符串对象。所以用的是同一个地址.结果为true.
System.out.println(s1==s2);
//返回结果:true

第二种方式:使用new创建

String s1 = "gja";
String s3 = new String("gja");
//当我们使用了new来构造字符串对象的时候,不管字符串常量池中有没有相同内容的对象的引用,
//新的字符串对象都会创建。所以即使内容相同,占用的也不是同一个地址.当比较地址的时候一定不同.但是比较内同的时候就是相同的啦
System.out.println(s1==s3);		//返回结果:false
System.out.println(s1.equals(s3));		//返回结果:true

对于使用new创建的字符串对象:
如果想将这个对象的引用加入到字符串常量池,可以使用intern方法。
调用intern后,首先检查字符串常量池中是否有该对象的引用,如果存在,则将这个引用返回给变量,否则将引用加入并返回给变量。

举例intern

String s1 = "gja";
String s3 = new String("gja");
String s4 = s3.intern();
//这里使用intern方法,将通过new创建字符串的对象的引用添加到常量池种.调用intern后,
//首先检查字符串常量池中是否有该对象的引用,如果存在,则将这个引用返回给变量,否则将引用加入并返回给变量。
System.out.println(s1==s4);		//返回结果true  原来的常量池中存在

面试题:
String s = new String(“xyz”); 产生几个对象?
一个或两个。如果常量池中原来没有 ”xyz”, 就是两个。如果原来的常量池中存在“xyz”时,就是一个。对于基础类型的变量和常量:变量和引用存储在栈中,常量存储在常量池中。
java中String new和直接赋值的区别
对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。

string,stringbuffer和stringbuilder的区别

String 字符串常量
Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
​字符串是常量;它们的值在创建之后不能更改。

--源码摘抄:public final class String,是一个最终类不能被继承
​ --源码摘抄:private final char value[];字符串是个常量,因为底层维护了char[]final的值不能改

StringBuffer 字符串变量(线程安全)适用多线程下在字符缓冲区进行大量操作的情况
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符

StringBuilder 字符串变量(非线程安全)适用于单线程下在字符缓冲区进行大量操作的情况
一个可变的字符序列。优化了字符串操作。
构造方法

StringBuilder() 
构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符。

StringBuilder的方法则没有synchronized关键字,所以不能保证线程安全,有可能会出现一些错误的操作

总结:
如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值