对于String的认识

本文通过示例代码详细解析了 Java 中 String 对象的创建过程,包括字符串池的作用及 intern 方法的使用,帮助读者理解 String 在 JVM 中的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这段时间有不少关于String的帖子,也有很多很好的解释。我在这里就算是搜集一下,并简单地分析一下原因。一是我不熟悉JVM的底层规范,二是我觉得别人分析的很好,但是不能拘泥于这样分析,分析的目的是为了让我们明白其中的道理。
下面我列出参考的帖子,也方便大家去查看:

《深入研究java对String字符串对象的创建以及管理》

《操作符“+”的定义,他是否是new了一个新的字符串?》

《到底创建了几个String对象?》

还是靠程序来说话:

  1. publicclassVerifyString{
  2. publicstaticvoidmain(Stringargs[]){
  3. Stringstr1="IamaString";
  4. Stringstr2="IamaString";
  5. Stringstr3=newString("IamaString");
  6. Stringstr5="Iama";
  7. Stringstr6="String";
  8. Stringstr7=str5+str6;
  9. Stringstr8="Iama"+"String";
  10. Stringstr9=str3.intern();
  11. Stringstr10=str7.intern();
  12. if(str1==str2)
  13. System.out.println("str1andstr2arethesameString.");
  14. else
  15. System.out.println("str1andstr2arethedifferentStrings.");
  16. if(str1==str3)
  17. System.out.println("str1andstr3arethesameString.");
  18. else
  19. System.out.println("str1andstr3arethedifferentStrings.");
  20. if(str1==str7)
  21. System.out.println("str1andstr7arethesameString.");
  22. else
  23. System.out.println("str1andstr7arethedifferentStrings.");
  24. if(str1==str8)
  25. System.out.println("str1andstr8arethesameString.");
  26. else
  27. System.out.println("str1andstr8arethedifferentStrings.");
  28. if(str1==str9)
  29. System.out.println("str1andstr9arethesameString.");
  30. else
  31. System.out.println("str1andstr9arethedifferentStrings.");
  32. if(str1==str10)
  33. System.out.println("str1andstr10arethesameString.");
  34. else
  35. System.out.println("str1andstr10arethedifferentStrings.");
  36. }
  37. }

运行的结果是:

  1. str1andstr2arethesameString.
  2. str1andstr3arethedifferentStrings.
  3. str1andstr7arethedifferentStrings.
  4. str1andstr8arethesameString.
  5. str1andstr9arethesameString.
  6. str1andstr10arethesameString.

解释以上的输出结果,首先要理解一个叫String Pool的概念,虽然JVM没有明确提出这个概念,但是细想一下,别的语言String基本都是作为基本类型来处理的,而在Java中直接就是一个对象,然而奇怪的是对象能像基本类型那样直接赋常量。这就能看出Java设计者的那种取舍吧,毕竟作为对象来处理的话,效率没有基本类型那样高。我们不需要更多的理解,直接记住String str1 = "I am a String";是把"I am a String"扔到了字符串池中,然后把引用抛给str1,以后再有相同值的String变量也是这种赋值语句的,那么还是存在字符串池中,有就直接返回引用,没有就创建一个新的。所以说着语句就创建了一个String对象。再看下一个String str3 = new String("I am a String");这个创建了几个对象?两个!不要怀疑!一个是在new String("I am a String")创建在heap中的,另一个是str3也在heap中,它们所指向的字符数组是相同的,位于内存区的常量池中。关于这一点,请看大企鹅的这篇blog:《还是 String》。接下来看str7和str8,明明两个的值是一样的,为什么结果不一样呢?这就牵扯到Java编译器对于不同str8的优化了。因为str7右边的是两个变量,而不是直接的两个值,编译器就无法在编译期间知道str8的值,相反,str8对于编译器来说直接就是str8 = "I am a String"了,这样的两种不同的情况,就有不同的结果了。再看str3和str7都和返回否定的,而为什么str9和str10返回的是一致的呢?因为intern()方法是把执行该方法的引用拖到了字符串池中,当然了如果字符串池中有的话,就直接返回引用了。

总结一下就是:
1. 区分好String str1 = "I am a String"和String str3 = new String("I am a String")创建对象的数目和地方。
2. 了解String str1 = "I am a " + "String"是编译期间确定值的。
3. 了解intern()方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值