java String创建字符串对象——面试java基础

在一次面试中,被问到这方面的问题,搞得我一脸蒙逼,那时候还没去了解JVM,为了以后不再出现这样的情况,我就在这里好好梳理一下String创建会创建多少个对象呢?

先看代码

public static void main(String[] args) {
        String str1 = "abc";
        String str2 = "a" + "b" + "c";
        System.out.println("结果1:" + (str1 == str2));
        String str3 = "a";
        String str4 = str3 + "bc";
        System.out.println("结果2:" + (str1 == str4));
        System.out.println("结果3:" + (str1 == str4.intern()));
        final String str5 = "a";
        String str6 = str5 + "bc";
        System.out.println("结果4:" + (str1 == str6));
    }

代码运行结果:

结果1:true
结果2:false
结果3:true
结果4:true

上面的运行结果需要从两个方面来说明:
一:java编译器
二:java字符串常量池

java编译器

我们来看看java编译器将上面的源码编译成了什么样子。(反编译结果)

public static void main(String[] args) {
        String str1 = "abc";
        String str2 = "abc";
        System.out.println("结果1:" + (str1 == str2));
        String str3 = "a";
        String str4 = str3 + "bc";
        System.out.println("结果2:" + (str1 == str4));
        System.out.println("结果3:" + (str1 == str4.intern()));
        String str5 = "a";
        String str6 = "abc";
        System.out.println("结果4:" + (str1 == str6));
    }

源代码和编译后的代码有很多不同点。str2和str6都变成了直接赋值为"abc",而str4却没有变化,这里也是java新手不太清楚的地方,其实由于常量字符串是在编译的时候就是可以被确定的,又因"a","b"和"c"都是字符串常量,因此变量str2的值在编译时就可以确定,同理因为str5被final关键字修饰,也相当于字符串常量,因此变量str6的值也在编译时就可以确定,代码编译后就和String str="abc"一样了。
也是因为上面的原因str4没有改变,因为str4并不能在编译期确定。

java字符串常量池

在执行代码String str1 = "abc"时,JVM先去字符串常量池中查找,看是否已经存在值为”abc”的对象,如果存在,则不再创建新的对象,而直接返回已存在对象的引用;反之,则先创建一个新的对象,然后加入到字符串池中,再将其引用返回。

String str1 = "abc";  // 会创建一个新的对象"abc"在字符串常量池中
String str2 = "abc";  // 因为字符串常量池中已经存在"abc",所以不会创建对象

这样结果1true,就可以理解了

String str3 = "a";  // 会创建一个新的对象"abc"在字符串常量池中
/* 
下面这行代码一共会创建三个对象:
  1. 会在字符串常量池中创建一个"bc"对象
  2. str3与 "bc" 进行字符串连接时,底层通过StringBuffer进行连接,生成一个
    StringBuffer对象(StringBuffer内部字符不考虑)
  3. 然后通过StringBuffer的append方法连接,通过toString()方法,将StringBuffer对象
    转为String,此时会产生一个新的堆内存地址,str4指向这个新的内存地址。
*/
String str4 = str3 + "bc"; 
// 因为str4在堆内存变量中,str1在字符串常量池中,所以==地址比较为false
System.out.println("结果2:" + (str1 == str4));
// str4.intern() 返回在字符串常量池中的"abc"引用,就和str1是同一对象,为true
System.out.println("结果3:" + (str1 == str4.intern()));

字符串相加推荐文章

看完上面的代码相信您已经对字符串创建对象个数有了一定的了解,接下来我们再来看看另一种情况。

/*
下面的代码,一共会创建两个对象:
  1. 在字符串常量池中创建"abc"对象
  2. 在堆中创建的原实例字符串对象
*/
String str1 = new String("abc");
// str1只是java栈中的对象引用

注意:String类型的引用是存在栈里。而字符串"abc"是存在字符串常量池中

// 在字符串常量池中创建一个"abc"对象
String str1 = "abc";
// 由于"abc"已经在字符串常量池中已经存在,所以不会再创建。
// 使用new关键字创建字符串,一定会在堆中创建一个实例,所以下面代码会创建一个对象
String str2 = new String("abc");
// str1只是java栈中的对象引用

注意:String类型的引用是存在栈里。而字符串"abc"是存在字符串常量池中

下面提升难度

  public static void main(String[] args) {
        String str1 = "a" + new String("b");
        String str2 = "ab";
        System.out.println(str1 == str2);
        String str3 = str2 + "c";
        str3.intern();
        String str4 = "abc";
        System.out.println(str3 == str4);
    }

运行结果:

false
true

注意:上面的运行结果和jdk版本有关,1.7和1.8都是上面的结果,1.7以下不是
上面的结果重点就是intern方法的作用,这里我只是抛砖引玉,想了解更多的读者可以看看下面的这篇博客:
深入解析String#intern

笔者个人能力有限,如有错误,请联系我修改。

最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容

  • 从网上复制的,看别人的比较全面,自己搬过来,方便以后查找。原链接:https://www.cnblogs.com/...
    lxtyp阅读 1,345评论 0 9
  • 前言 RTFSC (Read the fucking source code )才是生活中最重要的。我们天天就是要...
    二毛_coder阅读 452评论 1 1
  • 注:都是在百度搜索整理的答案,如有侵权和错误,希告知更改。 一、哪些情况下的对象会被垃圾回收机制处理掉 ?当对象对...
    Jenchar阅读 3,221评论 3 2
  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 829评论 1 6
  • 在编写程序的过程中,不了避免的要用到字符串,所以String类的常用方法的用法是必须掌握的。学习一个类的使用方法最...
    Geg_Wuz阅读 1,255评论 0 4