String类

本文深入解析Java中字符串的内存管理机制,包括字符串常量池、堆空间存储方式及字符串拼接过程中的变化。通过示例代码说明不同创建方式下字符串的行为特征。

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

以下为JDK1.6的说法
字符串内存结构图:
这里写图片描述
注意:字符串在底层的存储实际就是使用字符数组进行存储。
这里写图片描述

String str1 = "JavaEE";

首先在栈空间声明一个str1变量,然后看字符串常量池是否存在”JavaEE”,如果不存在,则在字符串常量池中新建”JavaEE”(字符数组)。这个值存在一个首地址,将这个首地址赋给str1。

String str2 = "JavaEE";

字符串常量区已经存在”JavaEE“,所以直接将”JavaEE“的首地址赋给str2。

String str3 = new String("JavaEE");

面试题:上述过程中创建了几个对象?答案是两个。
首先既然是new的,那么就要在堆空间开辟一个区域。但是记住字符串的真正内容并没有放在堆空间中,仍然在字符串常量池中。
这里写图片描述
可以从上面的代码看出:将字符串常量区的”JavaEE“的首地址(value–字符数组名)赋给刚才堆空间new出的一个实体中的value属性,然后再将堆空间中的实体的地址赋给str3.

String str5 = "Android";
str5 = str5 + "handoop";

首先也是在栈空间声明一个str5变量,然后看字符串常量池是否存在”Android”,如果不存在,则在字符串常量池中新建”Android”(字符数组)。这个值存在一个首地址,将这个首地址赋给str5。
第二步str5 = str5 + “handoop”;。这个要注意,并不是在字符串常量池中的”Android“后面直接加上”handoop“,而是重新在字符串常量池中新建一个”Androidhandoop“。
至于为什么是重新新建了,而不是在后面添加,这个很好理解。在前面已经提到字符串在底层的存储是以字符数组的形式的,数组在创建的时候大小已经确定了,如果直接在后面添加是不一定能放得下的。


简单示例:

import org.junit.Test;

public class TestString {
    @Test
    public void test(){
        String str1 = "JavaEE";
        String str2 = "JavaEE";
        String str3 = new String("JavaEE");
        String str4 = "JavaEE" + "Android";
        String str5 = "Android";
        String str6 = str1 + str5;  
        str5 = str5 + "handoop";
        String str7 = str6.intern();
        String str8 = "JavaEEAndroid";

        System.out.println(str1 == str2);//true
        System.out.println(str1 == str3);//false
        System.out.println(str1.equals(str3));//true

        System.out.println(str4 == str6);//false
        System.out.println(str4.equals(str6));//true
        System.out.println(str7 == str4);//true
        System.out.println(str4 == str8);//true

        Person p1 = new Person("AA");
        Person p2 = new Person("AA");
        System.out.println(p1.name == p2.name);//true

    }

}

class Person{
    String name;    
    Person(String name){
        this.name = name;
    }
}

有几个地方解释一下:
(1)

 System.out.println(str4 == str6);//false  为什么?

str4是在编译期就确定的值,为”JavaEEAndroid”。
str6涉及到变量的操作,编译期不确定具体值,加号两边在运行时会转换成new StringBuilder(str1).append(str5).toString(),而这个会产生一个新的字符串对象,所以与str4不相等。

(2)

String str4 = "JavaEE" + "Android";     
String str1 = "JavaEE";
String str5 = "Android";
String str6 = str1 + str5;  
String str7 = str6.intern();  //intern()的作用是什么?
System.out.println(str7 == str4);//true

intern()方法设计的初衷,就是重用String对象,以节省内存消耗。

详情见此 Java技术——你真的了解String类的intern()方法吗

        Person p1 = new Person("AA");
        Person p2 = new Person("AA");
        System.out.println(p1.name == p2.name);//true

从下面的内存结构图中可以看出显然是true。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值