文章目录

  • String s = new String("hello");创建了几个对象
  • 字符串常量拼接
  • 0、判断输出
  • 1、判断输出
  • 2、判断输出
  • 3、判断输出
  • 4、判断输出
  • 5、判断输出
  • 6、判断输出(String#intern()- - > jdk1.8)
  • 6、判断输出(String#intern()- - > jdk1.6)
  • 7、判断输出(String#intern()- - > jdk1.8)
  • 7、判断输出(String#intern()- - > jdk1.6)
  • 8、判断输出(String#intern()- - > jdk1.8)

String#intern()的作用是:运行期,将字符串动态加入字符串常量池,实现字符串对象复用,减小内存开销。

  • jdk1.6及之前,由于字符串常量池在永久代(方法区)中,和堆区不在同一内存区域。此时调用String#intern() 会先通过equals(key)查看字符串常量池中是否有该字符串存在,有则直接返回该字符串对象的引用,没有则将堆中的字符串复制一份,放到字符串常量池中,并保存复制到字符串常量池中的这个字符串对象的引用到hash表中,然后返回该字符串对象的引用。

  • jdk1.7及之后,字符串常量池被移至堆区的新生代中,此时调用String#intern()后,查找字符串常量池发现没有该字符串对象时,不再是将堆中的字符串对象赋值一份到字符串常量池中,而是将堆中的字符串对象的引用保存到hash表中,然后返回该字符串对象的引用。

String s = new String(“hello”);创建了几个对象

1个 或 2个

String s = new String("hello");  这段代码创建了几个字符串对象?

3个 或 4个 或 5个

String s = new String("he") + new String("llo");  这段代码创建了几个字符串对象?

1个

StringBuilder类的toString(), 底层是动态创建new String("hello"), 那么此时的new String(object)创建了几个字符串对象?

与jdk版本有关:(jdk1.6及之前是:3个 或 4个 或 5个 或 6个),(jdk1.7及之后是:3个 或 4个 或 5个)

String s = new String("he") + new String("llo");  这段代码创建了几个字符串对象?
String s1 = s.intern();

字符串常量拼接

对于字符串常量的拼接操作,编译期间编译器会对其进行优化。

public static void main(String[] args){String s1 = "he" + "llo"; //编译期会进行优化:等价与String s1 = "hello";String s2= "hello";System.out.println(s1==s2); //trueSystem.out.println(s1.equals(s2)); //true
}

对于字符串实例引用的拼接,编译器无法对其进行优化。在底层会调用new StringBuilder().append().toString()来生成对象引用。 并且 StringBuilder 类的 toString() 方法会生成新的String对象,所以二者不相等

public static void main(String[] args){String s0 = "he" + "llo";  //编译后会优化成hello: 等价于String s0 = "hello";String s1 = "he";String s2 = "llo";//s3不会被编译器优化,因为s1、s2是变量,后期是可能会发生变化的,所以编译器无法对他们进行优化。而是使用StringBuilder拼接:等价于String s3 = new StringBuilder().append(s1).append(s2).toString();String s3 = s1 + s2;System.out.println(s0 == s3); //falseString ss1 = "he";//ss3不会被编译器优化,因为ss1是变量,后期是可能会发生变化的,所以编译器无法对他们进行优化。而是使用StringBuilder拼接:等价于String ss3 = new StringBuilder().append(ss1).append("llo").toString();String ss3 = ss1 + "llo";System.out.println(s0 == ss3); //false
}
//StringBuilder类中toString()方法的源码
public String toString() {return new String(value, 0, count);
}

final修饰的字符串,再编译器也会进行优化

public static void main(String[] args) {String s0 = "hello";final String s1 = "he";final String s2 = "llo";String s3 = s1 + s2;  //编译后会优化成hello: 等价于String s3 = "hello";System.out.println(s0 == s3);  //true
}
public static void main(String[] args) {String s0 = "hello";final String s1 = "he";String s2 = s1 + "llo";  //编译后会优化成hello: 等价于String s2 = "hello";System.out.println(s0 == s2);  //true
}

0、判断输出

public static void main(String[] args) {String s1 = "hello";s1 = "world";System.out.println(s1 == s2);  //false
}

String s1 = “hello”;   //

s1 = “world”;   // String 底层被final修饰,已经创建就不允许被修改。这里表面是被修改了,实则是创建了一个新的字符串对象,并将新字符串对象的引用指向s1

1、判断输出

public static void main(String[] args) {String s1 = "hello";String s2 = "hello";System.out.println(s1 == s2);  //true
}

String s1 = “hello”;   //

String s2 = “hello”;   // 字面量方式创建字符串对象前,会先去检索字符串常量池,判断是否存有该字符串对象的引用。有则直接返回该引用。没有则在字符串常量池中创建一个字符串对象,并将该对象的引用保存到hash表中,然后再返回该对象的引用。

2、判断输出

public static void main(String[] args) {String s1 = new String("hello");String s2 = new String("hello");System.out.println(s1 == s2);  //false
}

String s1 = new String(“hello”);   //

String s2 = new String(“hello”);   //

3、判断输出

public static void main(String[] args) {String s1 = new String("hello");String s2 = "hello";System.out.println(s1 == s2);  //false
}

String s1 = new String(“hello”);   //

String s2 = “hello”;   //

4、判断输出

public static void main(String[] args) {String s1 = new String("hello");s1.intern();String s2 = "hello";System.out.println(s1 == s2);  //false
}

String s1 = new String(“hello”);   //

s1.intern();   // 由于没有定义变量来接收String#intern() 返回的引用,所以这里就不画图了

String s2 = “hello”;   //

5、判断输出

public static void main(String[] args) {String s1 = new String("hello");String s2 = s1.intern();String s3 = "hello";System.out.println(s1 == s2);  //falseSystem.out.println(s2 == s3);  //true
}

String s1 = new String(“hello”);   //

String s2 = s1.intern();   // StringTable中有保存hello字符串的对象引用,所以直接返回该对象引用

String s3 = “hello”;   //

6、判断输出(String#intern()- - > jdk1.8)

public static void main(String[] args) {String s1 = new String("he") + new String("llo");s1.intern();String s2 = "hello";System.out.println(s1 == s2);  //true
}

String s1 = new String(“he”) + new String(“llo”);   // 会创建5个字符串对象(也可能是3个)。在字符串常量池通过字面量创建"he" 和 “llo"字符串对象,并保存其对象引用,以及在堆中创建"he” 和 “llo"字符串对象,另外底层是通过new StringBuilder().append(“he”).append(“llo”).toString()进行拼接。其中StringBuilder的toString()会生成一个新的字符串对象new String(“hello”),但由于这个代码是运行期动态生成的,所以不会在字符串常量池中创建字符串对象"hello”,但会在堆中创建字符串对象"hello"

s1.intern();   // 在jdk1.7及以后,intern()方法会先去查看StringTable中是否已经有该字符串对象引用存在。没有则直接将在堆中创建的字符串对象的引用存到StringTable中 (jdk1.6之前,是直接赋值一份字符串对象到堆中,然后将赋值到堆中的那份字符串对象的引用存到StringTable中)。有则直接返回字符串常量池中的引用

String s2 = “hello”;   // 通过字符串的hash查找时,发现hash表中有该字符串对象引用存在,所以直接返回对象引用给变量s2。没有则再字符串常量池中创建一个字符串对象,然后将其引用保存到hash表中,然后返回该字符串对象引用给变量s2

6、判断输出(String#intern()- - > jdk1.6)

public static void main(String[] args) {String s1 = new String("he") + new String("llo");s1.intern();String s2 = "hello";System.out.println(s1 == s2);  //false
}

String s1 = new String(“he”) + new String(“llo”);

s1.intern();   // jdk1.8中调用intern()方法,会通过字符串的hash值查找StringTable中是否保存了该字符串的引用,有则直接返回该引用,没有则将堆中该字符串对象的引用存到StringTable中,然后再返回改该引用。 // jdk1.6则是判断StringTable中是否保存了该字符串的引用,有则直接返回该引用,没有则将堆中该字符串对象赋值一份到字符串常量池中,然后将复制的这份字符串对象的引用存到StringTable中,然后再返回该引用。

初学者注意啦:图中的"he" 字符串对象 和 new String(“he”)字符串对象只是为了让读者容易理解才这样表示而已,它们都是字符串对象,内部存储结构都是一样的。 // 所以别有:new String(“hello”)创建的字符串对象不是都放在堆中吗,怎么还能放到字符串常量池中啊,这样的错误理解。new创建的字符串对象确实是只能放在堆中,但这里我只是把这个字符串对象用new String(“hello”)形式表示而已,别把它理解成程序中的new String(“hello”)了】

String s2 = “hello”;   // 通过字符串的hash查找时,发现hash表中有该字符串对象引用存在,所以直接返回对象引用给变量s2。没有则再字符串常量池中创建一个字符串对象,然后将其引用保存到hash表中,然后返回该字符串对象引用给变量s2

7、判断输出(String#intern()- - > jdk1.8)

public static void main(String[] args) {String s1 = new String("he") + new String("llo");String s2 = s1.intern();String s3 = "hello";System.out.println(s1 == s2);  //trueSystem.out.println(s1 == s3);  //trueSystem.out.println(s2 == s3);  //true
}

String s1 = new String(“he”) + new String(“llo”);

String s2 = s1.intern();

String s3 = “hello”;

7、判断输出(String#intern()- - > jdk1.6)

public static void main(String[] args) {String s1 = new String("he") + new String("llo");String s2 = s1.intern();String s3 = "hello";System.out.println(s1 == s2);  //falseSystem.out.println(s1 == s3);  //falseSystem.out.println(s2 == s3);  //true
}

String s1 = new String(“he”) + new String(“llo”);

String s2 = s1.intern();   // 因为跨内存区域调用是不推荐的。所以jdk1.6之前String#intern()采用复制的方式。直到jdk1.7之后,字符串常量池被移至堆中,改为存引用方式

String s3 = “hello”;

8、判断输出(String#intern()- - > jdk1.8)

public static void main(String[] args) {String s1 = "hello";String s2 = new String("he") + new String("llo");String s3 = s2.intern();System.out.println(s1 == s2);  //falseSystem.out.println(s1 == s3);  //trueSystem.out.println(s2 == s3);  //false
}

String s1 = “hello”;   //

String s2 = new String(“he”) + new String(“llo”);   //

String s3 = s2.intern();   // String#intern() 会先去字符串常量池,通过字符串的hash查找,发现hash表中有该字符串对象引用存在,所以直接返回该引用

String s = new String(“hello“)创建了几个对象(图解)相关推荐

  1. string s = new string(“xyz“);创建了几个对象_「005」-JavaSE面试题(五):String类

    第一期:Java面试 - 100题,梳理各大网站优秀面试题.大家可以跟着我一起来刷刷Java理论知识 [005] - JavaSE面试题(五):String类 第1问:String.StringBuf ...

  2. java s1=abc s2=abc s1==s2_经典问题:String s1 = abc 与 String s2 = new String(abc)的区别...

    这是以前刚学Java那会经常被问到的问题,并且也会经常出现在面试中.这个问题不仅仅只局限于Java,可以适用于其他大部分语言,正好最近有个小朋友在学编程,特此整理一下. String s1 = &qu ...

  3. 创建和编辑AutoCAD对象(VBApython)

    创建python与CAD的连接 import win32com.client import pythoncomacad = win32com.client.Dispatch("AutoCAD ...

  4. 美团面试题:String s = new String(111)会创建几个对象?

    点击关注公众号,Java干货及时送达 来源:blog.csdn.net/o9109003234/article/details/109523691 String不可变吗? public class A ...

  5. 工作10年后,再看String s = new String(xyz) 创建了几个对象?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 转自:艾小仙 这个问题相信每个学习java的同学都不陌生, ...

  6. java中字符串的创建_【转载】 Java中String类型的两种创建方式

    本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...

  7. 云端飘 String s=new String(abc)创建了几个对象?

    转自:http://www.cnblogs.com/ydpvictor/archive/2012/09/09/2677260.html -------------------------------- ...

  8. 请别再拿“String s = new String(xyz);创建了多少个String实例”来面试了吧---转

    http://www.iteye.com/topic/774673 羞愧呀,不知道多少人干过,我也干过,面壁去! 这帖是用来回复高级语言虚拟机圈子里的一个问题,一道Java笔试题的.  本来因为见得太 ...

  9. String s=new String(abc)创建了2个对象的原因

    问题:String str=new String("abc"); 这行代码究竟创建了几个String对象呢? 相信大家对这道题并不陌生,答案也是众所周知的,2个. 接下来我们就从这 ...

  10. String s=a+b+c,到底创建了几个对象?

    首先看一下这道常见的面试题,下面代码中,会创建几个字符串对象? String s="a"+"b"+"c"; 如果你比较一下Java源代码和反 ...

最新文章

  1. 男人心疼女人的十种方式
  2. Jmeter(4)Http Cookie Manager
  3. VTK修炼之道54:图形基本操作进阶_表面重建技术(三角剖分)
  4. C++中的类所占内存空间总结
  5. .NET各版本一览表
  6. apache目录的访问控制
  7. G - Best ACMer Solves the Hardest Problem Gym - 101955G
  8. 【积少成多】vi的进阶使用
  9. php 长剑设计模式,PHP设计模式(创建型)
  10. 产生滚动条时JPanel的大小发生变化
  11. Java-JDK:JDK百科
  12. ffplay视频播放原理分析
  13. navicat中文破解
  14. 机房收费系统---概要设计说明书
  15. 计算机毕业设计asp.net193酒店客房预订网站系统
  16. 寒风里的凌厉香气,令人沉醉的男士魅力
  17. js实现类似栈和队列的行为,以及push和unshift两个方法的性能测试
  18. 面对复杂问题时,系统思考助你理解问题本质
  19. table表格表头单元格添加斜线
  20. 普林斯顿算法课Part2第四周作业_Boggle

热门文章

  1. 编译安装php7.3
  2. 「雕爷学编程」Arduino动手做(15)——手指侦测心跳模块
  3. [SoapUI] 在SoapUI中通过Groovy脚本执行window命令杀掉进程
  4. LightOJ 1278 - Sum of Consecutive Integers 分解奇因子 + 思维
  5. 有关VIM的一些笔记
  6. 未与信任 SQL Server 连接相关联
  7. SQL Server XML数据解析(1)
  8. Flutter ClipPath 自定义CustomClipper 玩转不一样的背景图案
  9. Mr.J-- jQuery学习笔记(十八)--自定义动画
  10. Tennis Game CodeForces - 496D(唯一分解定理,费马大定理)