String类(jdk1.8.0_191)之intern()方法探究
问题起源
疑惑起源于此,浏览论坛时看到这个东西,很疑惑为啥只是字符串不一样,就得到了不一样的结果呢?
问题探究
于是开始的纠结之路,
是否关键字
首先多来几个例子试试吧
经过验证常用关键字会返回false,而普通无意义字符串会返回true.
那java是关键字么?经过多处查询,好像都没有说java是关键字
关键字总览
分类 | 关键字 |
---|---|
访问控制 | private protected public |
修饰符 | strictfp synchronized transient volatile abstract class extends final implements interface native new |
程序控制 | break continue return do while if else for switch case default |
错误处理 | try catch throw throws |
包相关 | import package |
基本类型 | boolean byte char double float int long short true false |
变量引用 | super this void |
保留字: | goto const |
结论:虽然关键字会得到与java一样的结果,但是java却不是关键字,原因并不在此
intern()方法本身
既然猜的原因错了,那就看源码吧,但是这里有一个悲伤的故事,这是一个native方法,java源码中并不能看到源码…
机器翻译结果
/**
*返回字符串对象的规范表示形式。
*< P>
*字符串池最初是空的,由
*类{@code string}。
*< P>
*当调用intern方法时,如果池已包含
*字符串等于此{@code string}对象,由
*{@link equals(object)}方法,则池中的字符串是
*返回。否则,此{@code string}对象将添加到
*返回池和对此{@code string}对象的引用。
*< P>
*因此,对于任意两个字符串{@code s}和{@code t},
*{@code s.intern()==t.intern()}是{@code true}
*如果且仅当{@code s.equals(t)}是{@code true}。
*< P>
*所有文本字符串和字符串值常量表达式都是
*被拘留。字符串文本在
*Java&trade;语言规范。
*@返回与此字符串具有相同内容的字符串,但是
*保证来自唯一字符串池。
*/
总结:
----String intern()方法
用法解释:
当调用intern方法时,如果池已经包含与equals(Object)方法确定的相当于此String对象的字符串,则返回来自池的字符串。 否则,此String对象将添加到池中,并返回对此String对象的引用
看到这里,大概明白intern()方法是干嘛的了,于是开始代码验证.
从上边的测试代码可以看出,如果直接引用常量,intern()方法返回的也是常量池中的引用对象,
如果引用的是堆中的对象,且常量池中也有equals(Object),则返回常量池中的对象
但为啥test4中的结果就不一样了呢?我们的代码是不会向常量池中添加java这个字符串对象的,但结果仿佛是常量池中已经有了java这个字符串常量?
继续尝试
给字符串常量池加一个good,得到结果一致了,似乎是这个道理了,那么现在问题就变成了,常量池中的java到底是哪里来的了
似乎还是没有发现java这个字符串常量的出现,那估计java这个字符串就是在这个Demo执行之前出现的了
搜索JDK
发现jdk中存在java字符串常量,以及关键字常量,以及其他常量
最后验证
用其隔壁包的public final static String 常量做验证,果然这些常量也在程序执行之前被加入了字符串常量池
问题结论
由于常量池不存在good故s1.intern() == s1 返回true
而 常量池存在java故s2.intern() == s2 返回false
参考资料:https://www.cnblogs.com/liangyueyuan/p/9796992.html
https://blog.****.net/qq_26222859/article/details/73135660#commentBox
http://tangxman.github.io/2015/07/27/the-difference-of-java-string-pool/