JVM的知识这里总结的很详细:https://github.com/doocs/jvm/blob/master/README.md,因此在本博客也不会再对其中的东西重复总结了。

intern的作用

简单的讲,intern方法是把调用者丢到常量池里,并返回一个引用。

String s = new String("sq") + new String("666");      //line1
String s1 = s.intern(); //line2

以上代码line1在堆里创建两个字符串,并且拼接到一起。line2 是将这个凭借好的字符串放到常量池中,并返回一个指向常量池中的这个字符串的引用,在例子中赋给了s1。

为什么需要intern“多此一举”?因为是处理运行时生成的字符串

在上一篇讲常量池和JVM内存结构中说:初次创建字符串会自动在常量池中创建一个字符串。也就是说:new一个字符串时,会生产两个字符串,堆中一个,字符串常量池中创建一个,一共两个。那么,为什么还要调用intern() 方法呢?它起作用了吗?

我的理解是:new字符串时自动在字符串常量池也创建一个字符串(字符串常量池还不存在相同的字符串)仅限编译时的情况,而intern则是将程序运行时生成的字符串的引用丢一份进字符串常量池。

        像以上的情况,两个new运算符只是自动在池中创建了 “sq”   "666" 两个字符串,而没有 “sq666” ----因为这是在程序跑起来才通过“+”生成的。当程序跑到 line2 这里,就通过intern把  “sq666” 的引用也丢进池子。

不信?看如下例子:

片段1:
String s = new String("sq") + new String("666");
s.intern();
tring s2 = "sq666";
System.out.println(s == s2) //结果为true 片段2:
String s = new String("sq") + new String("666");
String s2 = "sq666";
System.out.println(s == s2) //结果为false

片段2 仅仅只比片段1少了 intern方法的调用,结果却相反。因为通过字面量创建字符串(即 String = "sq666")的方式只会生成一个字符串,放在池中,且如果池中已有这个字面量的字符串,则直接把引用指向这个已有的字符串即可,而不需重复创建。

综上,在程序跑起来时生成了 "sq666" 字符串,片段2没有把它丢进池子,所以通过字面量创建时又在池子中创建了一个新的,二者的地址自然也不相等了。片段1却是先把运行时生成的 "sq666" 的引用丢进了池子,这样通过字面量创建时发现池子中有现成的,不需要创建新的。因此二者地址自然也相等啦。

intern 随常量池的变化---只丢引用了

上一篇说到:随着元空间取代永久代,字符串常量池也不再存在于永久代,也不存在于元空间,而是存在于堆中。intern方法也有一些改变,以前intern方法是把这个字符串丢一份拷贝进字符串常量池,在这之后intern方法只是把字符串的引用丢一份进了字符串常量池。(也有不同意见:说还是丢的字符串内容,而非引用)

我认为丢的是一份引用,因为对于上述代码片段1返回的是true。我们假设: 运行时生成的字符串"sq666",地址为 ’oxa‘ ,如果调用intern是丢了一份拷贝版的字符串到池中,那么被丢进池的拷贝版字符串地址就肯定不是‘oxa’了(假设为’oxb‘),最后执行:String s2 = "sq666"; s2的内容就是`oxb‘,片段1应该返回的就是false了。

一些注意点:

String s = "sq"+"666";      经过优化是只在池中生成一个字符串的,即"sq666"

运行时生成字符串的情况还有: 调用StringBuilder的append方法等等

String类的intern()方法,随常量池发生的变化的更多相关文章

  1. JVM体系结构之七:持久代、元空间(Metaspace) 常量池==了解String类的intern()方法、常量池介绍、常量池从Perm-->Heap

    一.intern()定义及使用 相信绝大多数的人不会去用String类的intern方法,打开String类的源码发现这是一个本地方法,定义如下: public native String inter ...

  2. String类中intern方法的原理分析

    一,前言 ​ 昨天简单整理了JVM内存分配和String类常用方法,遇到了String中的intern()方法.本来想一并总结起来,但是intern方法还涉及到JDK版本的问题,内容也相对较多,所以今 ...

  3. Java技术——你真的了解String类的intern()方法吗

    0.引言 什么都先不说,先看下面这个引入的例子:   String str1 = new String("SEU")+ new String("Calvin") ...

  4. String类的intern()方法

    0.引言 什么都先不说,先看下面这个引入的例子: String str1 = new String("SEU")+ new String("Calvin"); ...

  5. Java String类的intern()方法

    该方法的作用是把字符串加载到常量池中(jdk1.6常量池位于方法区,jdk1.7以后常量池位于堆) 在jdk1.6中,该方法把字符串的值复制到常量区,然后返回常量区里这个字符串的值: 在jdk1.7里 ...

  6. JAVA中String类的intern()方法的作用

    一般我们变成很少使用到 intern这个方法,今天我就来解释一下这个方法是干什么的,做什么用的 首先请大家看一个例子: public static void main(String[] args) t ...

  7. String中的intern方法

    上一篇你真的会用String吗(3)-关于字符串拼接中我们提到了String.intern()方法,本篇我们就来详细的看下这个方法是干嘛的.首先来看下jdk8中这个方法的注释: When the in ...

  8. java.lang.String 类的所有方法

    java.lang.String 类的所有方法 方法摘要 char charAt(int index) 返回指定索引处的 char 值. int codePointAt(int index) 返回指定 ...

  9. 关于JAVA的String类的一些方法

    一.得到字符串对象的有关信息 1.通过调用length()方法得到String的长度. String str=”This is a String”; int len =str.length(); 2. ...

随机推荐

  1. 一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!

    1. 什么是KNN 1.1 KNN的通俗解释 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1 ...

  2. 命令用法习题,yum仓库的创建 chapter02 - 03 作业

    1.  分别用cat \tac\nl三个命令查看文件/etc/ssh/sshd_config文件中的内容,并用自己的话总计出这三个文档操作命令的不同之处? [root@localhost /]# ca ...

  3. JDK的命令行工具系列 (一) jps、jstat

    概述 在我们进行故障定位和性能分析时, 可以使用Java Dump(也叫Dump文件)来帮助排查问题, 它记录了JVM运行期间的内存占用和线程执行等情况.其中Heap Dump文件是二进制格式, 它保 ...

  4. zabbix监控WEB网站性能

    一直在纠结用什么实例来给大家演示呢?想来想去还是官方的好,那我们怎么用zabbix监控web性能和可用性呢?我们这边分为几个步骤:打开网站.登陆.登陆验证.退出,一共4个小step,看实例. 检测流程 ...

  5. 夯实Java基础(十三)——字符串

    字符串应该是我们在Java中用的最频繁.最多的,可见字符串对于我们来说是多么的重要,所以我们非常有必要去深入的了解一下. 1.String String就代表字符串,在Java中字符串属于对象.我们刚 ...

  6. spring-boot项目的docker集成化部署(一)

    目录 spring-boot项目的docker集成化部署 前言 基本思路与方案 基本步骤 准备源码 服务器和基础环境 结语 1. 本文总结: 2. 后期优化: spring-boot项目的docker ...

  7. MyBatis之#{} and ${}

    #{} 和 ${} 之间最大的差别就是  #{}会在使用的时候被加上 ‘’ 引号, ${}直接传值,不做任何处理 1.#{}对传入的参数会做预编译,也就是会当做字符串来处理 select * from ...

  8. 消息中间件-activemq实战之消息持久化(六)

    对于activemq消息的持久化我们在第二节的时候就简单介绍过,今天我们详细的来分析一下activemq的持久化过程以及持久化插件.在生产环境中为确保消息的可靠性,我们肯定的面临持久化消息的问题,今天 ...

  9. 映射&集合

    哈希函数 通过哈希表可以实现 O(1) 复杂度的查找. 哈希函数构造方法:设计好的哈希函数的两个基本原则,计算简单+分布均匀 1. 直接定址法 用key自身的某个线性函数来定址,f(key) = a* ...

  10. 为什么双重检查锁模式需要 volatile ?

    双重检查锁定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量.这个模式还可以用来创建单例.下面来看一个 Spring 中双重检查锁定的例子. 这个例子 ...