今天重新看了一点周志明大佬的《深入理解Java虚拟机》,发现这个地方讲的不是很透彻,在网络上看到一些博客基本也都是在搬运原文,搞得一头雾水。弄了半天算是彻底明白了,做一下笔记。

搬运一下原文对intern()方法的说明:String::intern()是一个本地方法,它的作用是如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象的引用(指的是常量池中的实例);否则,会将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用(指的是堆中的实例)。括号中是我的个人理解,由于作者两种情况说的结果都是"String对象的引用",让我错误地理解为都是堆中实例的引用。接下来我们看几段代码。

String a = "a";
String b = new String("a");
System.out.println(a == b);

上面这段代码结果显然是false,虽然两者值相等,但是a是字面量(常量池中),b在堆中(因为b是通过new创建)。

接下来我们看书中的这个例子:

String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);

结果是true,false。解释如下:"计算机软件"从未出现在常量池,因此str1.intern()的结果为堆中的值为"计算机软件"的String对象,同时也会将"计算机软件"这个字符串加入到常量池中;"java"曾出现在sun.misc.Version这个类中,因此早就存在于常量池里,所以str2.intern()的结果为常量池中的值为"java"的字面量。

再看看以下代码段:

String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str2.intern() == str2);

结果是true,false。这说明第一个intern()将"计算机软件"这个字符串加入到了常量池中,导致str2.intern()实际上是在常量池中,而str2在堆中。

String str1 = new String("计算机软件");
System.out.println(str1.intern() == str1);

这个结果是false,因为这样的构建String的方法会做两件事:在常量池中创建一个实例,再复制到堆中创建一个对象。这就导致str1.intern()实是在常量池中,而str1在堆中。

String str1 = new String("计算机软件");
System.out.println(str1.intern() == "计算机软件");

而这个结果是true,就很好理解了。

对String Intern()方法的理解的更多相关文章

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

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

  2. 浅析String.intern()方法

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

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

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

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

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

  5. 关于对String中intern方法的理解

    在java的String中有个一直被我们忽视了的方法intern方法:它的官方解释是:一个初始时为空的字符串池,它由类 String 私有地维护. 当调用 intern 方法时,如果池已经包含一个等于 ...

  6. String intern 方法 jdk中的描述

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

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

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

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

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

  9. String intern()方法详解

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

随机推荐

  1. 牛客编程巅峰赛S1第5场 - 黄金&钻石&王者 B.牛牛的字符串 (DP)

    题意:有一个字符串\(s\),我们可以选择\(s_{i}\),如果\(s_{i+k}>s_{i}\),那么就可以交换\(s_{i}\)和\(s_{i+k}\),问最多能够交换多少次. 题解:因为 ...

  2. SSH 密钥认证

    目录 SSH协议概述 SSH 和 Telnet 的区别 SSH 相关命令 SSH 验证方式 基于密钥的安全认证 SSH 优化 expect 脚本免交互登录 sshpass 免交互登录 SSH协议概述 ...

  3. LINUX - 最简单的CS通信实例

    服务端[编译:gcc server.c -o server] #include <stdio.h> #include <sys/socket.h> #include <s ...

  4. wordpress 插件安装 Too Many Requests

    解决办法是在插件界面不直接点击安装/更新,右键新标签页打开链接,会有下载地址. 下载后上传插件即可.

  5. codeforces 1037E-Trips 【构造】

    题目:戳这里 题意:n个点,每天早上会在这n个点中加一条边,每天晚上最大的子图满足子图中每个点都有k条或以上的边. 解题思路:看了官方题解,先把所有的点都连上,再从最后一天往前减边,用set维护最大的 ...

  6. redis键过期时间

    redis服务器中每个数据库都是一个redisDb,而redisDb实质上是一个字典的模型,数据库的每一个键都是一个字典的键值,对数据库的增删改查也就是对字典对象的增删改查. redis在维护带有过期 ...

  7. Cortex-M系列内核 启动文件分析

    最近终于闲了下来了准备好好学习下Cortex-M3/M4系列处理器的架构,经过各种资料的折磨也没法对它的整个工作过程能有个完整的认知,最后看到一片博客打算从程序的运行过程开始探究,所以首先就找到了启动 ...

  8. js load more select

    js load more select searchable scroll load more append to list refs xgqfrms 2012-2020 www.cnblogs.co ...

  9. GitHub Actions in Action

    GitHub Actions in Action https://lab.github.com/githubtraining/github-actions:-hello-world https://g ...

  10. 使用 js 实现一个简易版的模版引擎

    使用 js 实现一个简易版的模版引擎 regex (function test() { this.str = str; })( window.Test = ...; format() { let ar ...