字符串编译期与运行期分析及字符串常量池

首先直接看这样的两个字符串的声明:
    String s1 = new String("TestString");

    String s2 = "TestString";
对于这样两个字符串的声明在内存中的分布如下图:

这里写图片描述
字符串s1由于是new的结果,那么首先s1作为一个变量会在栈内存中开辟空间用来保存该变量,然后在堆内存中开辟一块空间用来保存这个字符串对象,同时,也正是因为s1作为一个字符串,在开辟字符串对象空间的同时,在堆内存中也会把该字符串常量保存在字符串常量池当中,所以说,一次new的字符串对象会在堆内存当中产生两个字符串对象。

对于字符串s2这种初始化赋值的方式,首先会在字符串常量池当中进行寻找,如果字符串常量池当中包含该字符串,则直接将该变量指向该字符串常量,如果不包含该字符串,则会新创建一个字符串常量到字符串常量池当中。

上述两种字符串创建的方式,s1会创建两个字符串对象,其中一个是new在堆内存上的字符串对象,一个是在字符串常量池中保存的一份字符串,而s2有可能不用创建对象,若该常量字符串存在则不需要再次进行创建,若不存在则需要在字符串常量池当中进行创建。

接下来看一下字符串在编译期和运行器的分析比较

同样先来一段代码:
public class StringObject {
    public static void main(String[] args) {
        //eg1
        String a = "a1";
        String a1 = "a" + 1;
        System.out.println(a == a1); //true

        //eg2
        String b = "b1";
        int bb = 1;
        String b1 = "b" + bb;
        System.out.println(b == b1); //false

        //eg3
        String c = "c1";
        final int cc = 1;
        String c1 = "c" + cc;
        System.out.println(c == c1); //true

        //eg4
        String d = "d1";
        final int dd = getDd();
        String d1 = "d" + dd;
        System.out.println(d == d1); //false
    }

    public static int getDd(){
        return 1;
    }
}
上述四种情况用来比较两个字符串对象是否为同一个对象
对于eg1中的a1和a,由于两个变量都是常量字符串,当变量a初始化后就会在字符串常量池当中含有”a1”字符串,创建a1时就会先从字符串常量池当中寻找,此时就会找到,直接将已有的字符串常量对象赋值给a1变量,因此a1和a的对象比较结果就相同。
对于eg2中的b1和b,由于bb是一个变量,因此只有在运行期才能确定,所以返回结果为false
对于eg3和eg2中的区别在与变量cc使用了final修饰符,也就是说此处的cc相当于一个常量,在编译期已经将其替换,所以就和eg1类似,两个字符串对象为为同一个对象
然而对于eg4,虽然变量dd前也使用了final进行修饰,但是变量dd的值本身是通过一个静态方法的返回值进行初始化的,方法的执行是在运行期,所以结果为两个对象不是同一个对象。

!!!!初次学习,不正之处,望指正!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值