【JVM】对String::intern()方法深入详解(JDK7及以上)

这篇具有很好参考价值的文章主要介绍了【JVM】对String::intern()方法深入详解(JDK7及以上)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、什么是intern?

String::intern()是一个本地方法,它的作用是如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象的引用;否则,会将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。----书上描述

已经包含。。。可能不太好理解。我画图解释
【JVM】对String::intern()方法深入详解(JDK7及以上),jvm,java,开发语言
方法的执行顺序肯定是从下向上依次执行的。
String s1 = “11”; 先去字符串常量池中查看是否已经存在“11”,如果存在则直接返回"11"的地址,如果不存在则会在字符串常量池中创建“11”,然后返回创建好的“11”的地址。因为之前未创建过,所以该指令会先去字符串常量池中创建“11”,然后返回11的地址 501
String s2 = new String(“11”); 也是先去字符串常量池中查看是否已经存在“11”,如果有就在堆中创建对象,存的是字符串常量池中“11”的地址501,最后,将堆中对象的地址601返回给S2 。
String s3 = s2.intern(); intern方法会从字符串常量池中,查询当前s2字符串"11"是否存在,若不存在就会在字符串常量池中创建字符串"11"的实例, 由于s1已经在字符串常量池中已经创建了“11”,s2.intern()则返回501。

System.out.println(s1==s2);
System.out.println(s1==s3);

false
true

s1==s2 返回false是因为s1指向的是字符串常量池中的"11"对象(501),而s2指向的是堆中存储了"11"的地址的对象(601)
s1==s3 返回true 是因为s3和s1都指向的是字符串常量池中的"11"。

对String srt = new String(“str”)与 str1 = ”str“的区别不了解的话可以看篇文章

2、经典例题解释

例1

//1
String s = new String("1");
//2
s.intern();//调用此方法之前,字符串常量池中已经存在了"1".
//3
String s2 = "1";
//4
System.out.println(s==s2);
  • 执行1,会创建两个对像,在字符串常量池中创建一个”1“,在堆中创建一个String对象,并存储“1”在字符串常量池中的的地址。
  • 执行2,调用此方法之前,字符串常量池中已经存在了"1",所以此指令什么都没做,此时s指向堆中的对象。
  • 执行3,由于字符串常量池中已经存在了“1”,所以不需要再创建,返回“1”的地址,s2指向字符串常量池中的”1“。
  • 执行4,由于s指向堆中对象,s2指向字符串常量池中的对象,所以打印结果是false。

这是比较简单的例子
下面上强度了!!!!!!

例2

		//1
		String s3 = new String("1")+new String("1");
		//2
        s3.intern();
        //3
        String s4 = "11";
        //4
        System.out.println(s3==s4);
  • 执行1,会在堆中创建两个存储字符串”1“的地址的对象和一个字面量为”11“的String对象,在字符串常量池中创建一个”1“字符串实例。
    在编译期间,在创建String对象之前,会先创建一个StringBuilder对象,后面每次在堆中创建完一个String对象,会对该字符串执行LDC指令,LDC指令会先到字符串常量池中查找是否存在对应字符串实例的引用,如果有的话,那么直接返回这个字符串实例的地址给堆中的new的String对象,如果没有的话,会创建一个字符串实例,然后将其添加到字符串常量池中,之后再返回这个字符串实例对象的地址给堆中创建的对象。完成String对象初始化后,都会执行StringBuilder::append()方法,将该字符串拼接到StringBuilder对象里。当都拼接完,会执行StringBuilder::toString()方法,返回一个在堆中新new的String对象,value为"11"。
    可以通过编译后的字节码文件清晰的观察整个过程:
    【JVM】对String::intern()方法深入详解(JDK7及以上),jvm,java,开发语言
    标注的都是刚才介绍的行为。

  • 执行2,由于toString()方法只在堆中创建了一个”存储11"的String对象,并没有在字符串常量池中创建"11"字符串实例。按之前的说法intern应该去字符串常量池中创建字符串”11“的实例,但是在JDK7中,并没有在字符串常量池中创建字符串"11"的实例,由于堆中已经存在了"11"这个String对象,那么为了节省空间,会在字符串常量池中申请一块空间,存放这个String对象的地址,并返回存放的地址,也就是堆中存储"11"的String对象的地址。

  • 执行3,会去字符串常量池中查找是否存在"11",因为第二行已经在字符串常量池中,创建了存储堆中存储"11"的String对象的地址的空间,则直接返回空间里面存储的堆中String对象的地址,所以s4也指向了堆中存储"11"的String对象。

  • 由于s3和s4都指向堆中同一个对象,所以打印结果为true。
    如图所示:
    【JVM】对String::intern()方法深入详解(JDK7及以上),jvm,java,开发语言
    通过debug,可以看到两个句柄指向的地址是一样的:
    【JVM】对String::intern()方法深入详解(JDK7及以上),jvm,java,开发语言
    打印结果:
    【JVM】对String::intern()方法深入详解(JDK7及以上),jvm,java,开发语言文章来源地址https://www.toymoban.com/news/detail-658439.html

例3

		//1
		String s3 = new String("1")+new String("1");
		//2
        String s4 = "11";
        //3
        s3.intern();
        //4
        System.out.println(s3==s4);
  • 第一行执行结果与例2的第一行执行结果一致。
  • 执行2,由于字符串常量池中,还没有"11",则向字符串常量池中创建字符串"11"的实例,并返回实例的地址。
  • 执行3,由于字符串常量池中已经存在"11",则不需要再创建,返回实例的地址,但由于没有赋值操作,所以该行代码没有什么作用。
  • 此时,s3指向堆中存储了“11”的String对象,而s4指向的是字符串常量池中字符串为"11"的实例,所以指向的地址不同打印结果为false
    通过debug可以看到两个句柄指向的地址是不同的:
    【JVM】对String::intern()方法深入详解(JDK7及以上),jvm,java,开发语言
    打印结果:
    【JVM】对String::intern()方法深入详解(JDK7及以上),jvm,java,开发语言

到了这里,关于【JVM】对String::intern()方法深入详解(JDK7及以上)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【jvm系列-08】精通String字符串底层原理和运行机制(详解)

    JVM系列整体栏目 内容 链接地址 【一】初识虚拟机与java虚拟机 https://blog.csdn.net/zhenghuishengq/article/details/129544460 【二】jvm的类加载子系统以及jclasslib的基本使用 https://blog.csdn.net/zhenghuishengq/article/details/129610963 【三】运行时私有区域之虚拟机栈、程序计数器、本地方法栈 https

    2023年04月17日
    浏览(93)
  • 深入理解JVM虚拟机第十三篇:详解JVM中的程序计数器

    😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取! 🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

    2024年02月08日
    浏览(54)
  • 深入理解JVM虚拟机第二十七篇:详解JVM当中InvokeDynamic字节码指令,Java是动态类型语言么?

     😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨ 2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群: 583783824   📚📚  工作微信: BigTreeJava 拉你进微信群,免费领取! 🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

    2024年02月04日
    浏览(44)
  • Java JVM 堆、栈、方法区详解

    目录 1. 栈 2. 堆 3. 方法区 4. 本地方法栈 5. 程序计数器 首先来看一下JVM运行时数据区有哪些。 在介绍JVM栈之前,先了解一下  栈帧  概念。 栈帧:一个栈帧随着一个方法的调用开始而创建,这个方法调用完成而销毁。栈帧内存放者方法中的局部变量,操作数栈等数据。 Jav

    2024年01月19日
    浏览(47)
  • JVM中方法区、永久代、元空间详解以及关系?

    首先我们需要先复习一下jvm的大致内存图,如下: 哦~ ,想起来了,原来方法区属于jvm的运行时数据区,且作用就是存储类信息、方法信息、常量池信息等静态数据。  (补充一下:运行时数据区中的红色是指方法区和堆是线程共享的,其他几个都是线程私有的) 好的,回想

    2024年02月09日
    浏览(32)
  • JDK JRE JVM

    JDK是用于开发、编译、调试和运行Java应用程序的软件包,包含了Java编程语言的开发工具和Java运行时环境。JDK包括Java编译器(javac)、Java虚拟机(JVM)和Java类库,提供了一套完整的工具和环境来进行Java应用程序的开发。 JRE是用于运行Java程序的软件包,包含了Java虚拟机(

    2024年02月16日
    浏览(53)
  • JVM 垃圾回收详解之内存分配和回收原则+死亡对象判断方法

    当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。 Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时,Java 自动内存管理最核心的功能是 堆 内存中对象的分配与回收

    2023年04月19日
    浏览(58)
  • 003 JDK、JRE、JVM

    JDK的全称是Java Development Kit, 它是Java程序开发工具包,包含了JRE和编译器等开发工具。 JRE的全称是 Java Runtime Environment,它是Java程序的运行时环境,包含了JVM和运行时所需要的类库。 JVM的全称是Java Virtual Machine,它是Java虚拟机,Java程序在此容器内运行,这就是区别于C/C++语

    2024年01月22日
    浏览(40)
  • 「 JavaSE 」String、StringTable、String.intern()详解

    参考鸣谢 深入解析String#intern 美团技术团队 再议String-字符串常量池与String.intern() gcoder_ JVM系列之:String.intern和stringTable 程序那些事 看了这篇文章,我搞懂了StringTable robod 字符串常量池StringTable Mr_cdd Java中的字符串(String)是一种不可变对象,它在许多应用程序中扮演着重要角

    2023年04月08日
    浏览(34)
  • 从JVM指令看String对象的比较

    在翻看各类 java 知识中,总会提到如下知识:比较 String 对象,例如: 在刚学习 java 知识的时候,对于这个结果感到非常意外且不理解,还曾一度尝试去死记硬背。虽然网上的文章也有对此分析居多,但是在接触 JVM 后,发现原因其实非常简单。 在将代码编译成的字节码后,

    2024年02月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包