Logo

郎哥编程

String对象的内存分配

2020-01-07 196

String对象有三种创建方式:

第一种方式是直接通过赋值语句,将字符串赋值给String类型的变量。

例如:

String  str = “Hello”;

第二种方式是通过new运算符,实例化一个String对象,并将对象引用赋值给String类型的变量。

例如:

String  str = new String(“Hello”);

第三种方式是通过String对象的intern()方法返回一个String对象的引用。

例如:

String  str = “Hello”. intern();

前面String对象的三种创建方式,虚拟机对其内存分配上是有所区别的,先来看第一种创建方式。

第一种创建方式是通过赋值语句直接将字符串赋值给String类型的变量。在这种创建方式中,虚拟机会在方法区的常量池中判断是否存在具有和字符串(如Hello)内容相同的String对象:如果常量池不存在和赋值字符串内容相同的对象,虚拟机就在常量池中分配内存并创建该String对象,并将String对象的引用赋值给String类型的变量;如果常量池存在与赋值字符串内容相同的对象,虚拟机会直接将该对象的引用赋值给String类型的变量。这种创建方式对连续创建同一字符串内容的String对象特别有用,内存利用效率非常高效。

第二种创建方式是通过new运算符实例化String对象,并将new运算符返回的对象引用赋值给String类型的变量。在这种创建方式中,虚拟机会创建两个String对象:一个String对象是在常量池中创建,如果常量池中已有字符串内容相同的对象,则不创建;一个String对象是在运行数据区的堆中创建,将在常量池中创建的String对象的字符数组复制到在堆中创建的String对象。

String类型的变量接收new运算符返回的对象引用后,如果使用赋值语句对该String类型的变量重新赋予不同的字符串内容,该变量将会指向一个新的String对象,该String对象会在常量池中创建。

案例1:建立StringTest1类,在类的main()方法内部,使用new运算符实例化一个String对象,返回的对象引用赋值给String类型的变量str,输出str指向对象的哈希码,然后使用赋值语句将新的字符串内容赋值给str,输出str指向对象的哈希码,验证哈希码是否一致。

在memory包下新建StringTest1类。代码如下:

public class StringTest1 {
 
    /** 
    * @Title: main 
    * @Description: Java程序入口main方法
    * @param @param args    参数 
   
    * @return void    返回类型 
    * @throws 
    */
 
    public static void main(String[] args) {
       // 实例化String对象
       String str = new String("Hello");
       System.out.println("str对象的哈希码:" + str.hashCode());
       // 修改str对象的内容
       str = "Hello World";
       System.out.println("str对象修改后的哈希码:" + str.hashCode());
 
    }
 
}

程序执行结果如下图所示:

image.png

从程序的执行结果可以看出,当对str重新赋值不同的内容后,虚拟机会在常量池创建一个新的String对象,并将该对象的引用赋值给str。

第三种创建方式是通过String对象的intern()方法来返回一个String对象的引用。在这种创建方式中,虚拟机会首先判断在常量池中是否存在“Hello”字符串对象,如果存在就直接返回该对象的引用,否则就在常量池创建该对象,并返回对象的引用。

前面String对象的内存分配经常用到常量池,常量池是虚拟机从运行数据区的方法区划分出来的一块内存区域,JDK1.8将常量池放置到运行数据区的堆区域。常量池主要用来存储字面常量、使用final修饰的变量以及符号引用。字面常量包括数值常量(如36、100等)、字符串常量(如“123”、“abc”等)。符号引用是指用一组符号来描述引用的目标,符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可。例如编译器会把对象的引用作为一个符号引用,因为编译器不知道对象引用在内存的实际地址,当虚拟机加载类到运行数据区并初始化类后,虚拟机会把这些符号引用转换为直接引用(指向目标的内存地址,如对象在堆中的内存地址)。

代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论