关于String s=""和String s=new String("")的一些理解

话不多说,首先看一段代码。

        String a = "a";
        String b = "a";

        String x = new String("a");
        String y = new String("a");

        System.out.println(a == b);//输出true
        System.out.println(x == y);//输出false
        System.out.println(a == x);//输出false
        System.out.println(x.equals(y));//true
        System.out.println(x.equals(a));

原因分析:

首先需要明白String其实是一个常量类对象,底层代码是final关键字修饰的char数组。
String a=”a”,这句代码在运行时不会在堆内存新建一个String对象,而是会去常量区寻找是否存在“a”这个常量,如果存在,就把“a”这个常量在方法区的地址赋值给栈中的a;如果不存在,那么就在常量区创建“a”常量,然后再把地址赋值给a,所以String a = “a”;
String b = “a”;执行之后,a和b中的值都是“a”在常量区中的地址,所以两者用==或者equals比较时都是true。

String x = new String(“a”);这句代码就不一样了,代码运行时,会在堆中创建新的String对象,对象值为“a”,然后把该对象地址赋值给栈中的x。String x = new String(“a”);String y = new String(“a”);执行之后,堆中就有两个对象,对象值都是“a”,但两个对象的地址不同,且地址分别存放在x和y中,所以x==y会输出false, x.equals(y)会输出true。

特别提醒,虽然a存储的是常量区中“a”的地址,x存储的是堆中“a”的地址,但是因为两者指向的内存中存储的值一样,所以a.equals(x)返回的就是true.

好啦,上面的理解了,再来了解下别的花样。

        String x="a";
        String z1="a"+"haha";
        String z=x+"haha";

        System.out.println(z==z1);//false
        System.out.println(z.equals(z1));//true

个人理解。String z=x+”haha”;由于编译器无法确定x是否会发生改变,所以无法进行优化,这句就等价于String z=new String(“ahaha”);所以也就是堆中创建新String对象,值为“ahaha”,地址赋值给了栈中的z。但是,如果x设计为常量类型,即final String x=”a”,则由于x不能再重新赋值,所以String z=x+”haha”;在执行时,编译器可以进行优化,等价于String z1=”ahaha”。
而 String z1=”a”+”haha”;这句代码,在编译时,编译器会对语法进行优化,编译器会自动识别此为拼接操作,所以这句代码在编译完成之后,等价于String z1=”ahaha”;

所以,如果被问到String s=”a”+”b”+”c”+“d”+“e”是创建了几个对象?答案应该是1个。
但如果是String s=a+b+c+d的话,创建了几个对象呢,我觉得应该用到了会新建一个StringBuffer对象,然后依次调用append方法,将a,b,c,d追加进去,最后调用toString()返回一个String对象,所以应该也是创建了一个String对象,也会创建一个StringBuffer对象,个人感觉这么问问题就没什么意思了,明白底层如何实现应该就行了。

猜你喜欢

转载自blog.csdn.net/m0_37942202/article/details/82534234