java中的String

文章介绍了Java中创建字符串对象的两种方式以及`intern()`方法在JDK6和JDK8中的行为差异,重点在于字符串常量池、堆和方法区(元空间)的角色。在JDK6中,`intern()`会复制字符串实例;而在JDK8中,仅记录引用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)创建字符串对象
//方式1
String str = "abc";
//方式2
String str = new String("abc");

方式1表示:在字符串常量池(String Pool)中先寻找值为 “abc” 的内存地址,如果找不到,则开辟内存,赋值该内存地址为 “abc”,然后将该内存地址传递给变量 str,str 直接指向字符串常量池中值为 “abc” 的内存地址。

方式2表示:先在堆(Heap)空间中开辟空间,new String对象,然后再去字符串常量池中寻找值为 “abc” 的地址,如果找到,则把该地址的引用传给 new String对象;如果找不到,则开辟内存,赋值该内存地址为 “abc”,然后把该地址的引用传给 new String对象。最后,把堆空间中 new String 对象的地址,传递给 str,str 指向堆空间中的对象。

(2)intern()
public class HelloWorld {
    public static void main(String[] args) {
        String s1 = new String("hello") + new String("world");
        s1.intern();
        String s2 = "helloworld";
        System.out.println(s1==s2);
    }
}

jdk1.6输出:false

jdk1.8输出为:true

JDK 6中,intern()方法会把首次遇到的字符串实例复制到永久代的字符串常量池
中存储
JDK 8中,intern()只需要在常量池里记录一下首次出现的实例引用即可
   在JDK 8中,在调用后发现StringTable中没有所对应的字符串。
String s1 = new String("hello") + new String("world");
这句代码会在堆中new一个String对象(其实并没有这么简单,后面讲)
s1.intern();
s1调用了intern方法,然后发现在StringTable中并没有所对应的字符串,
那么jvm就会在StringTable中放入一个地址,这个地址指向s1所new的String对象。
String s2 = "helloworld";
jvm发现在StringTable中已经存在指向"helloworld"的地址了,就会把StringTable中的
地址给s2。此时s1和s2都指向这个地址。所以是同一个对象。于是返回了true

public class HelloWorld {
    public static void main(String[] args) {
        String s1 = new String("hello") + new String("world");
        String s2 = "helloworld";
        s1.intern();
        System.out.println(s1==s2);
    }
}

jdk1.8输出为:false

方法区是《Java虚拟机规范》中规定的一个内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。

元空间是方法区的实现。方法区的实现,JDK1.7之前是永久代,JDK1.8之后是元空间。

永久代在物理上是堆的一部分,元空间内存是操作系统本地内存。

Jdk1.7之前类的元数据、静态变量、字符串常量池都是在永久代
jdk1.8之后类的元数据在本地内存,静态变量和字符串常量在堆内存,相当于方法区只有类的元数据

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值