Java创建字符串的两种方式在地址上的区别

简介: Java创建字符串的两种方式在地址上的区别

一、JAVA中字符串的两种创建方式


我们知道,在Java中有两种创建字符串对象的方式:

1)采用直接赋值的方式赋值


String str1 = "abc";

       采用这种方法去创建字符串时,JVM会在方法区的字符串常量池中寻找这个字符串是否存在,如果存在则不去创建,让创建的对象直接引用其在字符串常量池中的地址;如果不存在则在字符串常量池中创建这个字符串并且返回这个字符串在常量池中的地址。

image.png

编辑

2)采用new关键字新建一个字符串对象


String str2 = new String("abc");
复制代码

       采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"abc"这个字符串如果有,则不在池中再去创建"abc"这个对象了,直接在堆中创建一个"abc"字符串对象,然后将堆中的这个"abc"对象的地址返回赋给引用str,这样,str就指向了堆中创建的这个"abc"字符串对象;如果没有,则首先在字符串池中创建一个"abc"字符串对象,然后再在堆中创建一个"abc"字符串对象,然后将堆中这个"abc"字符串对象的地址返回赋给str引用,这样,str指向了堆中创建的这个"abc"字符串对象。

注意:这种方法本质是在堆区引用字符串常量池中的地址,每次new的对象,在堆上都会创建一个新的对象指向常量池。

image.png

编辑

这两种创建方法其实在创建性能上和访问上是有区别的。(堆区创建带来的性能开销)

二、两种创建方法字符串指向比较


public class Demo1 {
    public static void main(String[] args) {
        String str1 = "abc";
        String str2 = new String("abc");
        String str3 = "abc";
        System.out.println(str1.equals(str2));
        System.out.println(str1 == str2);
        System.out.println(str1 == str3);
    }
}

image.png编辑

这两种方法创建出的字符串虽然内容是一样的,但指向是不一样的。str1和str3直接指向的是常量池的地址,str2指向堆的地址。(参考上面两个图)。

再看下面的代码:

public class Demo1 {
    public static void main(String[] args) {
        String str1 = "abcdef";
        String str2 = "abc";
        String str3 = "def";
        String str4 = "abc" + "def";
        String str5 = str2+str3;
        String str6 = new String("abc"+"def");
        System.out.println(str1 == str4);
        System.out.println(str1 == str5);
        System.out.println(str1 == str6);
    }
}

image.png编辑

这里的str1 == str4很好理解,“abc” + “def”这一步在编译期间会合并成“abcdef”所以输出true;str1 == str5这里的str5出现这样的结果,别的一些说法认为只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入字符串池中。对于所有包含new方式新建对象和直接运用字符串变量的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,都放在了堆内存中。

我对str5的理解是因为str2和str3以及是存在的对象了,所以寻找的第一位置是堆内存所以它并不会再进一步去其对应的常量池中寻找拿出再去拼接这两段字符串。所以只能将他俩在堆区完成操作并且放在堆中导致返回结果是false。

指向地址查看:


public class Demo1 {
    public static void main(String[] args) {
        String str1 = "abcdef";
        String str2 = "abc";
        String str3 = "def";
        String str4 = "abc" + "def";
        String str5 = str2+str3;
        System.out.println(System.identityHashCode(str1));
        System.out.println(System.identityHashCode(str2));
        System.out.println(System.identityHashCode(str3));
        System.out.println(System.identityHashCode(str4));
        System.out.println(System.identityHashCode(str5));
    }
}

image.png

编辑

这样就很明显的看出这些创建方式对象的引用是什么了。

总结:


       new创建出的对象指向均不相等,字符串的创建无论是哪种方式,都需要先在字符串常量池中寻找该字符串是否存在。

如果有不正确的地方请指出,欢迎一起讨论!


相关文章
|
1天前
|
算法 Java Go
【经典算法】LeetCode28 找出字符串中第一个匹配项的下标(Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode28 找出字符串中第一个匹配项的下标(Java/C/Python3实现含注释说明,Easy)
3 0
|
1天前
|
存储 算法 Java
【经典算法】LeetCode 151. 反转字符串中的单词(Java/C/Python3实现含注释说明,中等)
【经典算法】LeetCode 151. 反转字符串中的单词(Java/C/Python3实现含注释说明,中等)
5 0
|
1天前
|
存储 算法 Java
【经典算法】LeetCode 1170:比较字符串最小字母出现频次(Java/C/Python3实现含注释说明,中等)
【经典算法】LeetCode 1170:比较字符串最小字母出现频次(Java/C/Python3实现含注释说明,中等)
6 0
|
2天前
|
Java 程序员 编译器
蓝易云 - Java:Exception和Error有什么区别?
总的来说,Exception和Error的主要区别在于他们的用途和处理方式。Exception是可以被程序员处理的问题,而Error则是程序无法处理的严重问题。在编写代码时,程序员应该尽力处理可能出现的异常,但是对于错误,除非你知道如何处理,否则最好让程序终止,因为继续运行可能会导致更严重的问题。
7 0
|
2天前
|
Java
Java 数组转字符串
Java 数组转字符串
|
2天前
|
Java
Java 截取字符串中指定的分隔符放入list中
Java 截取字符串中指定的分隔符放入list中
|
3天前
|
Java
java后台拼接字符串查询语句@小霸王
java后台拼接字符串查询语句@小霸王
|
3天前
|
安全 Java 测试技术
滚雪球学Java(50):理解Java中String、StringBuilder和StringBuffer的区别与选择
【6月更文挑战第4天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
10 0
滚雪球学Java(50):理解Java中String、StringBuilder和StringBuffer的区别与选择
|
3天前
|
Java 编译器
15. 【Java教程】字符串
15. 【Java教程】字符串
14 4
|
3天前
|
NoSQL Java Redis
【Redis】 Java操作Redis客户端命令——基础操作与字符串操作
【Redis】 Java操作Redis客户端命令——基础操作与字符串操作