首先我们来看一段代码:

public class InternTest {
  
  public static void main(String[] args) {
    String str1 = new String("hello") + new String("world");
    str1.intern();
    String str2 = "helloworld";
    System.out.println(str1 == str2);//true
    System.out.println(str1.intern() == str2);//true
  }
}
大家对上面代码的运行结果一定很疑惑吧,第二个为true可以理解,因为intern的返回值本来就是该常量在常量池中的地址,但是为什么第一个也是true呢?
那么是什么导致的呢?答案就是这个intern的实现方式。
在jdk1.7之前的版本,调用这个方法的时候,会去常量池中查看是否已经存在这个常量了,如果已经存在,那么直接返回这个常量在常量池中的地址值,如果不存在,则在常量池中创建一个,并返回其地址值。
但是在jdk1.7以及之后的版本中,常量池从perm区搬到了heap区。intern检测到这个常量在常量池中不存在的时候,不会直接在常量池中创建该对象了,而是将堆中的这个对象的引用直接存到常量池中,减少内存开销。
所以调用第二行代码的时候,就是将heap中的地址值存放到常量池中,多以第三行代码获取的就是该字符串在heap中的地址值。
如果我们将第二行代码和第三行代码的顺序调换:
public class InternTest {
  
  public static void main(String[] args) {
    String str1 = new String("hello") + new String("world");
    String str2 = "helloworld";
    str1.intern();
    System.out.println(str1 == str2);//false
    System.out.println(str1.intern() == str2);//true
  }
}
public class InternTest {
  
  public static void main(String[] args) {
    String str1 = new String("java");
    str1.intern();
    String str2 = "java";
    System.out.println(str1 == str2);//false
    System.out.println(str1.intern() == str2);//true
  }
}

这个结果其实很好理解,在第一行代码执行的时候,会在heap中创建一个对象,并且回去常量池中查看该字符串是否已经存在,如果不存在,那么久创建一个。所以第二行代码可以说是没什么作用的。

作者:Mazin

来源:my.oschina.net/u/3441184/blog/887152

- END -
推荐阅读:

干货 | 深入分析 string.intern() 方法的更多相关文章

  1. 常量池之String.intern()方法

    JDK7将String常量池从Perm区移动到了Java Heap区.在JDK1.6中,intern方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中的实例.但是在JDK1.7以后,Str ...

  2. String放入运行时常量池的时机与String.intern()方法解惑

    运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念 ...

  3. 浅析String.intern()方法

    1.String类型“==”比较样例代码如下:package com.luna.test;public class StringTest { public static void main(Strin ...

  4. String.intern() 方法__jdk1.6与jdk1.7/jdk1.8的不同

    1.为什么要使用intern()方法 intern方法设计的初衷是为了重用string对象,节省内存 用代码实例验证下 public class StringInternTest { static f ...

  5. 字符串常量池和String.intern()方法在jdk1.6、1.7、1.8中的变化

    字符串常量池也是运行时常量池 jdk1.6中,它是在方法区中,属于“永久代” jdk1.7中,它被移除方法区,放在java堆中 jdk1.8中,取消了“永久代”,将常量池放在元空间,与堆独立了 pub ...

  6. String intern 方法 jdk中的描述

    一个初始为空的字符串池,它由类 String 私有地维护. 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中 ...

  7. String intern()方法详解

    执行以下代码 String a1=new String("abc");       String a2=new String("abc");       Sys ...

  8. 对于JVM中方法区,永久代,元空间以及字符串常量池的迁移和string.intern方法

    在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普 ...

  9. 深入理解String.intern()方法

    首先进入intern()的源码中, 首先说一点:1.7后的JVM为String在方法区中开辟了一个字符串常量池,如果一个String()不是new()出来的,都将在常量池中拿字符. 注释翻译过来就是, ...

随机推荐

  1. 项目的Servlet类找不到

    先右击项目,

  2. oracle 获取时间

    1.获取当前时间的前24小时的各小时时间段 select to_char(to_date(to_char(sysdate ) ,'yyyy-mm-dd hh24') || ':00:00','yyyy ...

  3. 兼容pc端和移动端的轮播图插件 swiper.js

    swiper.js是一款纯JavaScript打造的滑动特效插件,可以用来实现检点轮播图,tab触摸滑动切换等常用效果.下载地址:https://www.swiper.com.cn/download/ ...

  4. 9、kubernetes之statefulset控制器

    一.StatefulSet 有状态副本集 必要的三个组件:headless service.StatefulSet.volumeClaimTemplate 准备pv apiVersion: v1 ki ...

  5. Dubbo Admin 控制台

    下载项目源码 https://github.com/apache/incubator-dubbo-admin 解压后配置 zookeeper 地址,路径为 dubbo-admin-server/src ...

  6. DB2日常管理

    执行时间最长的10条SQL语句(按时间降序排列),可保存为脚本方便调用:db2 "SELECT rows_read / (num_executions + 1) as avg_rows_re ...

  7. 万变的Web,不变的CRUD

    用JSP+Servlet写程序,到Struts,Spring,hibernate写程序,到现在Spring Cloud分布式写程序,到底有多大区别,是不是还在写CRUD? 看着JD上各种要求,简直是S ...

  8. LaTex&&markdown

    LaTeX在线编辑器:传送门 LaTeX常用公式整理(转载):传送门 Markdown洛谷教程(转载):传送门 Markdown基本语法(转载):传送门 Markdown数学符号和语法(转载):传送门 ...

  9. php array function

    说明:不特殊说明都支持php4,5,7 参考:https://www.php.net/manual/zh/ref.array.php   is_array ( mixed $var ) : bool ...

  10. SAE中Python无法创建多线程的解决方案

    最近在SAE上开发了一个给kindle退送书的小公众号(kindle免费书库),由于微信对http响应时间 有限制,而推送本身是发邮件,当附件一大就很容易超时而使得用户收不到应答.一开始我是想通过多线 ...