我是风筝,公众号「 古时的风筝 」,一个不只有技术的技术公众号,一个在程序圈混迹多年,主业 Java,另外 Python、React 也玩儿的 6 的斜杠开发者。 Spring Cloud 系列文章已经完成,可以到 我的 github 上查看系列完整内容。也可以在公众号内回复「 pdf 」获取我精心制作的 pdf 版完整教程。
前些天在我的一个 Java 技术交流群里有一个小伙伴提出了和字符串常量池相关的问题,各位同学各抒己见,虽然很多结论都是正确的,但最终还是没有完全说清楚字符串常量池的原理,所以我决定写一篇关于字符串常量池的文章。
文章前两天在这里发布了,仰仗各位同学喜爱,到目前位置获得了50多个赞。原文地址: 《包你懂系列》Java 字符串常量池漫游指南(图文并茂)
在文章发布后有同学提出了疑问,后来又有两个同学评论,疑问都来自于同一个点,就是当调用 new String()
的时候到底会不会到字符串常量池里创建。
开始我也并没有在意,因为这个问题其实很普遍,直到有第三个同学提出问题,我心里有点打鼓,难道我真的搞错了吗?于是,我赶紧从头到尾的重读文章,终于发现了问题所在。
在介绍 new String() 方式 和 intern() 池化 这两节的时候,例子和图里的代码是有问题的,使用 new String 方法的时候里面跟的参数是一个字面量,像下面这样
String s2 = new String("古时的风筝"); 复制代码
但是,这样的例子是不正确的,不应该用字面量当参数,应该像下面这样
String a = "古时的"; String s2 = new String(a + "风筝"); 复制代码
虽然原文中的结论都是正确的(这也让我的心情稍微好了一点点),但是代码其实都是我根据结论推到出来的,没有经过验证,但是这样的例子其实是得不出这种结论的,因为我忽略了一个根本问题。
特别感谢 @Maxifi 同学在评论中准确的提出了这个问题,当时,看到这个评论,马上意识到了文章中的问题,差点吓出一身冷汗。
虽然结论是对的,但是根据我之前的例子其实是不能推导出来的。
一切都是源于这个问题,我文章中画了那么多图,其实最主要的就是为了解释这个问题。
下面所说的所有结论都是基于 JDK 1.7 及其之后的版本。
我之前的例子是这样的:
String s2 = new String("古时的风筝"); 复制代码
这种情况下会发生什么呢? 首先,"古时的风筝" 这就是个字面量,只要是字面量就会到字符串常量池去创建,和下面的声明语句一样
String s = "古时的风筝"; 复制代码
都会到字符串常量池去创建。 所以如果用字面量做参数的话,我之前文章中所说的「字符串常量池之前已经存在相同字符串」和 「字符串常量池中不存在相同内容的常量」这两种情况其实只会发生第一种。
而且可能会造成很多同学认为正确但其实是错误的结论:
new String() 的时候,如果发现字符串创量池不存在相同的字符串,就去创建。
这个结论是错误的,之所以造成这种假象的原因是因为参数是字面量,而不是因为 new String()。
比如下面的这两行代码,
String a = "古时的"; String s2 = new String(a + "风筝"); 复制代码
有参数不是字面量,所以最终 “古时的风筝”这个字符串不会因为 new String() 而到字符串常量池去创建。
写文章这件事,分享出来给别人只是一个方面,好像是读到的人有了收获,其实并不然,写文章的过程对写作者来说才是受益匪浅的。
要说实现什么功能,相信这里99%的同学都能拍着胸脯说没有问题。但是,涉及到原理性的问题,很多时候,很多人都是一知半解。比如说我,有时候觉得做开发也有些年了,很多东西都是手到擒来的,但是当有人过来问的时候,往往思考半天也不能完全正确的回答,更多的时候,自己理解,但是表述的时候,就完全不是那么回事了。
在这里发过文章的同学肯定也有类似的经历,刚开始准备写的时候意气风发,写着写着发现,我去,我是谁,我在哪儿,我怎么好像不是很理解这块,不对,那块儿也不是很理解。计划 1、2 个小时写完的文章,可能为了解答自己的疑问,翻书、查相关文档,断断续续能写上两三天,甚至更长。
在这个查阅、梳理的过程中,才真正加深了自己的理解,当我们把知识点完全梳理出来,并且清晰的形成书面文档的时候,知识才属于我们自己。否则,真的不知道你认为你掌握的知识是不是真的属于你。
在写作过程中发现有疑问的地方,往往也是其他人有疑问的地方。并且网上的文章都大同小异,甚至有的是错误(比如我之前发的那一版,就差点贻笑大方了)。
那么同一问题,遇到两种或多种不同的解释的时候,应该怎么排除错误项呢。首先,当发现你看到内容和你的理解相悖的时候,应该合理怀疑,然后进一步查证。
我的做法一般如下:
先多翻出来几篇文章对比一下,多方对比一下,只是对比,但是不会采纳;
如果有官方网站、官方文档的话,就去官方文档上看;
如果有源码的话,就去翻源码(前提是能看懂的源码);
需要画图的就画图,画图的过程真的对理解问题很有帮助,而且文章写出来也清晰;
关于技术性的文章,其实每篇都会写不少时间,最怕的就是出现纰漏,甚至是错误。技术实战型的倒是还好,由于这种原理性的,搞不清楚就会出现问题,甚至颠倒黑白,以至于最后贻笑大方,甚至误人子弟。
这不上一篇文章就出现了问题,以后写文章更要多加调研,仔细核对。
上一篇文章中不恰当的例子和图片已经做了更正,并且在评论区做了统一回复,希望看过那篇的文章的同学再回头去看一篇,别被之前的例子误导。
我是风筝,公众号「 古时的风筝 」,一个在程序圈混迹多年,主业 Java,另外 Python、React 也玩儿的很 6 的斜杠开发者。可以在公众号中加我好友,进群里小伙伴交流学习,好多大厂的同学也在群内呦。