java中String详解

String类在java中是一个比较特殊的类,它可以有两种创建形式:

说String之前需要说明jvm中内存结构的变化:

jdk1.6:方法区叫永久代,而字符串常量池和静态变量都存放在永久代中,字符串常量池有存放的默认阈值1009,可以用-XX:StringTableSize: 设置常量池的大小,但是如果过大,会导致PermSpace的OutOf Memory异常
jdk1.7: 方法区还是叫永久代,但是将字符串常量池和静态变量移出永久代,放入堆中,防止占用过多的永久代的空间,可以利用堆中的垃圾回收器进行回收,默认常量池的大小为60013
jdk1.8:方法区叫元空间(MetaSpace),不再受jvm内存大小的控制,受系统内存的限制,但是字符串常量池和静态变量的位置并没有变化,常量池大小至少为1009,默认大小也是60013

String创建方式

一.用双引号扩起来,比如String s = “hello”;
二.普通对象的声明方式,String s = new String(“hello”);
三.字面量拼接的方式,String s = “hello” + “world”;
四.有变量存在的拼接方式,String s = s1 + “hello”;
四种声明方式的不同,对象的创建方式也会有所不同。

第一种方式String s = “hello”:这是一种字面量的创建方式,这种方式会把hello字符串放入堆中的字符串常量池,并且s指向该值的指针,就是指向字符串常量池的指针。
字节码分析:ldc #2 表示#2位置的值也就是hello
放入到字符串常量池(但是官方文档写着是放入到运行时常量池,字符串常量池和运行时常量池应该还是有区别的),astore_1表示栈顶元素弹出放入到局部变量表1的位置

在这里插入图片描述
在这里插入图片描述

第二种方式String s = new String(“hello”):如果之前字符串常量池中没有创建过hello字符串,则遇到双引号的hello先会在常量池中创建hello,然后再在堆中创建一个为"hello"的字符串对象。
字节码分析:
new指令表示对象的分配,详见我对应写的文章java中对象的五个步骤的前四步。
dup指令表示一个栈顶元素并且压入栈,这时候就会存在两个一样的元素在栈顶位置,这样是为了执行invokespecial指令,表示执行String对象的构造器方法,这时操作数栈会弹出一个栈顶元素(消耗一个对象,之后那个对象变为栈顶元素,让程序员自己操作)
ldc上面已经解释过了,不再赘述。
invokespecial指令执行String对象的构造器方法(init)
astore_1指令将栈顶元素弹出,放入局部变量表的索引1位置
在这里插入图片描述

第三种方式String s = “hello” + “world”:如果是字面量的拼接操作,则在代码编译期间就会进行优化,直接将拼接之后的字符串放入字符串常量池中
在这里插入图片描述
第四种方式:String s = s1 + “hello”:如果存在其他变量拼接的操作时,会有很大的变化。
1至2行表示创建了一个s1的字符串"a",仔细看第三行的变化,这时候new出了一个StringBuilder对象,这个对象就是用来对+符号来拼接操作的。后面有aload_1操作,从局部变量表索引1的位置的指针元素压入操作数栈中,意思就是将s1字符串压入操作数栈进行后面的append操作,后面ldc再将hello字符串压入栈进行append操作,最后调用一个StringBuildertoString方法会返回一个新的String对象,至此字符串才拼接完成。所以只要有其他变量参与的拼接操作,都会产生一个StringBuilder对象,最后执行执行一个toString方法返回一个新的String对象。
在这里插入图片描述
所以字符串拼接的时候务必要使用StringBuilder的append方法,如果线程不安全,则需要使用StringBuffer拼接,否则会创建很多新的String对象

intern详解

public native String intern();
源码中是一个native方法;
由于stringtable在1.6之后的调整,这个方法也有一定的调整。
如果该字符串在stringtable中存在,则返回该字符串的内存地址。这个逻辑是固定不变的。但是如果字符串在stringtable中不存在,则会有区别。
1.6,因为原字符串对象和stringtable的位置是堆和方法区,所以当字符串在stringtable不存在时,会在stringtable中创建一个字符串对象,并且返回新创建字符串对象的地址
1.7以上,由于字符串对象和stringtable的位置都是堆,所以只需要复制原字符串的内存地址赋值放入到stringtable中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值