Java-String对象初始化与字符串常量池

11 篇文章 1 订阅

我们都知道在Java中,String对象有两种初始化方式:一种是直接进行字符串的赋值;另一种是通过new 关键字方式初始化。他们两者之间到底有什么区别呢?字符串常量池又是什么东西呢?


String对象的初始化方式

方式一:

String str1 = "Hello";//直接赋值实例化,入池保存

此时我们来分析一下,该过程的内存模型如下:

在这里插入图片描述

通过直接赋值的方式为String类对象实例化时,会在栈上生成对象的引用str,并会在堆上的字符串常量池上开辟一块内存,用来存放字符串常量。如果该字符串常量已经存在下次就不会在开辟新的内存空间用来存储该常量,而是直接将新的对象引用指向该字符串在常量池里的位置。
类似于下面这种情况:

String str1 = "Hello";//直接赋值实例化,入池保存
String str2 = "Hello";//常量池已存在,自动引用

str2就会直接引用str1在实例化时在字符串常量池创建的字符串对象。其内存模型如下:
在这里插入图片描述

方式二:

String str = new String("Hello");//new关键字构造方法实例化

由于使用关键字new就一定以为着会开辟新的堆内存空间,这块空间就是为了传入构造方法的字符串数据
下面分析一下使用构造方法实例化的内存模型:

在这里插入图片描述

因为每个字符串都是String类的匿名对象*,所以字符串池中没有“Hello”字符串的话,会在常量池中新创建该对象,其*只负责实例化新的String类对象。而后用关键字new开辟另一块堆空间,将栈引用指向该新创建的String对象。而常量池中的“Hello”常量,如过内有其他引用指向就会成为垃圾空间,等待被JVM的GC回收

总结:使用new关键字创建,会开辟两块内存空间,不仅会浪费内存,而且实际的内容总是存在堆上新开辟的非池空间上,常量池的空间会成为垃圾空间等待回收。

什么是字符串常量池

Java为了避免产生大量的字符串对象,设计了一个字符串池(String Pool)其本质是一个动态对象数组,通过直接赋值方式初始化创建的字符串对象都会存在于字符串池中,且字符串池中的字符串不会重复,以便可以被共享使用提高存储效率。在Java中的常量池其实分两种。

1)静态常量池:
是指程序(.class)文件在加载时候会将程序中保存的字符串、普通的常量、类和方法等信息,全部进行分配。

2) 运行时常量池:
是指当一个和程序(.class)加载之后,有一些字符串内容是通过String对象的形式保存后在实现字符串连接处理,由于String对象的内容可以改变,所以此称为运行时常量池。

举个栗子:静态常量池

String strA = "HelloWorld";//开辟新对象并入池
String strB = "Hello"+"World";//使用+进行字符串连接,由于所有都是常量,实际上表示一个字符串
System.out.println(strA==strB);//判断结果:true

举个栗子:运行时常量池

String strA = "HelloWorld";//开辟新对象并入池
String strB = "World";
String strC = "Hello"+strB;
//使用+进行字符串连接,动态拼凑时,由于strB是变量其内容运行时可能改变,所以其无法从常量池获取字符串引用
System.out.println(strA==strC);//判断结果:false

字符串常量池位置

JDK6.0及之前版本:

字符串常量池是放在Perm Gen区(也就是方法区)中;

在JDK7.0版本:

字符串常量池被移到了堆中了。

小思考

留下一些判断供大家思考,有疑惑的可以留言交流。

        String s1 = "Hello";
        String s2 = "Hello";
        String s3 = "Hel" + "lo";
        String s4 = "Hel" + new String("lo");
        String s5 = new String("Hello");
        String s6 = s5.intern();
        String s7 = "H";
        String s8 = "ello";
        String s9 = s7 + s8;

        System.out.println(s1 == s2);  // true
        System.out.println(s1 == s3);  // true
        System.out.println(s1 == s4);  // false
        System.out.println(s1 == s9);  // false
        System.out.println(s4 == s5);  // false
        System.out.println(s1 == s6);  // true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值