String的intern()方法详解

news2024/12/29 9:37:44

文章目录

  • 前言
  • 一、new String()创建了几个对象?
  • 二、Stting a=new String("ab")+new String("c")创建了几个对象
  • 三、String的intern()方法
  • 四:面试题
  • 五:总结


前言

在开发过程中很多朋友,由于不会正确使用intern(),导致开发的程序,执行效率比较差。同时最近发现一道非常有意思的关于intern()的面试题,这道面试题还是有不小的难度,相信很多朋友看到以后也不知道怎么解答,所以今天咱们深入详解下intern()。

Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java ™ Language Specification.


当调用intern()时,如果池子里已经包含了一个与这个String对象相等的字符串,正如equals(Object)方法所确定的,那么池子里的字符串会被返回。否则,这个String对象被添加到池中,并返回这个String对象的引用。
注意:这里说的池子就是字符串常量池,大白话就是,调用intern()后,如果String对象的值如果在字符串常量池中,直接返回常量池中的地址,否则这个String对象将被添加到字符串常量池中,并返回字符串常量池中的地址。
由此可见,对于任何两个字符串s和t,当且仅当s.equals(t)为真时,s.intern() == t.intern()为真。
所有字面字符串和以字符串为值的常量表达式都是interned。


一、new String()创建了几个对象?

 public static void main(String[] args) {
 		 // 2个对象
 		// 对象1:new String()的时候会在字符串常量池创建一个"abc"的字符串
 		// 对象2:在堆空间创建一个a对象
            String a=new String("abc");
            
         // 1个对象
         // 在字符串常量池创建一个"ab"的字符串对象   
            String b="ab";
    }

jvm内存结构分为方法区、堆、java虚拟机栈、本地方法栈、程序计数器等。当我们执行上面方法时。

  1. 首先将当前main方法压入java虚拟机栈的栈帧中。
  2. 在编译期的时候jvm会帮我们创建局部变量表,也就是我们当前方法的局部变量表。
  3. 局部变量有两个变量a和b,
    局部变量a的地址指向的是堆空间的对象a,对象a指向的是字符串常量池的“abc”
    局部变量b的地址指向的是字符串常量池的"ab";

二、Stting a=new String(“ab”)+new String(“c”)创建了几个对象

 public static void main(String[] args) {
			// 6个对象
			// 对象1:new String("ab") 在堆空间创建一个对象
			// 对象2:new String("ab") 在字符串常量池创建"ab"
			// 对象3:new String("c") 在堆空间创建一个对象
			// 对象4:new String("c") 在字符串常量池创建"c"
			// 对象5:创建StringBuffer对象,在我们进行符串拼接的过程中,java底层会使用StringBuffer使用append进行拼接
			// 对象6:最后会调用StringBuffer的tostring方法在堆空间创建abc对象
            String abc=new String("ab")+new String("c")
                    
    }

在上述例子当中我们一共创建了6个对象。可能大家都好奇,字符串"abc"怎么没有去创建。因为在我们StringBuffer中,它会单独维护一个char数组去创建我们拼接的字符串,所以这里就不会去字符串常量池申请"abc"
在这里插入图片描述


三、String的intern()方法

当调用intern()时,如果池子里已经包含了一个与这个String对象相等的字符串,正如equals(Object)方法所确定的,那么池子里的字符串会被返回。否则,这个String对象被添加到池中,并返回这个String对象的引用。

注意:这里说的池子就是字符串常量池,大白话就是,调用intern()后,如果String对象的值如果在字符串常量池中,直接返回常量池中的地址,否则这个String对象将被添加到字符串常量池中,并返回字符串常量池中的地址。

    public static void main(String[] args) {
        String a=new String("abc");
        String b="abc";
        System.out.println(a==b); // false


        String a1=new String("abcd").intern();
        String b1="abcd";
        System.out.println(a1==b1); // true

    }

第一个案例是false,其实在上面已经和大家解释过了,第一个a指向的是堆空间的a对象(字符串"abc存储在a对象当中"),第二个b指向的是字符串常量池的"abc" 所以是false。

第二个案例是true,因为当我们创建a1时,它首先还是会先在堆空间创建a对象,然后在字符串常量池创建"abcd"字符串,堆空间的a对象指向字符串常量池的"abcd"。因为我们调用了intern()方法,所以在这里它会直接返回的是字符串常量池的“abcd”地址。 b1则是直接指向字符串常量池的"abcd",所以返回结果是true。

    public static void main(String[] args) {
        String a = new String("ab") + new String("c");
        String b = "abc";
        System.out.println(a == b); // false

        String a1 = new String("ab") + new String("cd");
        a1.intern();
        String b1 = "abcd";
        System.out.println(a1 == b1); // true
    }

在上述这个案例中,第一个打印的是false第二个打印的是true。

第一个案例false,其实在上面已经和大家解释过了,第一个a指向的是堆空间的a对象(字符串"abc存储在a对象当中"),第二个b指向的是字符串常量池的"abc" 所以是false。

第二个案例是true,因为在这个案例中,我们a1指向的是堆空间的a1对象,a1对象里面存储了我们的"abcd",当我们调用intern()方法时,它会去字符串常量池创建一个对象,然后把当前对象的地址指向我们的a1的堆空间地址。(这里会有点绕,因为我们已经创建了字符串"abcd",所以为了节省空间。就不会在去字符串常量池去申请一个"abcd",而是直接创建一个对象指向我们堆空间的a1对象)


四:面试题

有了对以上的知识的了解,我们现在再来看常见的面试或笔试题就很简单了:

Q:下列程序的输出结果:
String s1 = “abc”;
String s2 = “abc”;
System.out.println(s1 == s2);
A:true,均指向常量池中对象。

Q:下列程序的输出结果:
String s1 = new String(“abc”);
String s2 = new String(“abc”);
System.out.println(s1 == s2);
A:false,两个引用指向堆中的不同对象。

Q:下列程序的输出结果:
String s1 = “abc”;
String s2 = “a”;
String s3 = “bc”;
String s4 = s2 + s3;
System.out.println(s1 == s4);
A:false,因为s2+s3实际上是使用StringBuilder.append来完成,会生成不同的对象。

Q:下列程序的输出结果:
String s1 = “abc”;
final String s2 = “a”;
final String s3 = “bc”;
String s4 = s2 + s3;
System.out.println(s1 == s4);
A:true,因为final变量在编译后会直接替换成对应的值,所以实际上等于s4=”a”+”bc”,而这种情况下,编译器会直接合并为s4=”abc”,所以最终s1==s4。

Q:下列程序的输出结果:
String s = new String(“abc”);
String s1 = “abc”;
String s2 = new String(“abc”);
System.out.println(s == s1.intern());
System.out.println(s == s2.intern());
System.out.println(s1 == s2.intern());
A:falsefalsetrue。

Q:下列程序的输出结果:
  String a=new String("abc");
  String b="abc";
  System.out.println(a==b); 
  String a1=new String("abcd").intern();
  String b1="abcd";
  System.out.println(a1==b1); 
A:falsetrue


Q:下列程序的输出结果:
     String a = new String("ab") + new String("c");
     String b = "abc";
     System.out.println(a == b); 
     String a1 = new String("ab") + new String("cd");
     a1.intern();
     String b1 = "abcd";
     System.out.println(a1 == b1); 
A:falsetrue

五:总结

对于程序中大量使用存在的字符串时,尤其存在很多已经重复的字符串时,使用intern()方法能够节省内存空间。

大的网站平台,需要内存中存储大量的字符串。比如社交网站,很多人都存储:北京市、海淀区等信息。这时候如果字符串都调用intern()方法,就会很明显降低内存的大小。

以下是java在不同版本中String字符串的内存变化,希望可以对你有所帮助。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1098467.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue.config.js配置proxy代理产生404错误的原因

在使用vue做开发时,请求api接口时为了解决跨域问题,一般会设置proxy代理, 但有时候会莫名其妙的出现404错误,这里总结一下vue设置proxy代理产生404错误的几种原因: 原因1:没有注意vue proxy代理优先级的规…

SQL Server向表中插入数据

SQL Server向表中插入数据 切换到对应的数据库 use DBTEST插入数据 方式1 insert into 表名(列名1,列名2) values(数据1,数据2)注意: 列名就算是字符类型也不用加引号,数据如果对应的字段是字符串类型&…

48.排列问题求解

思路分析&#xff1a;通过为每一队分配一个id&#xff0c;join条件要求t1.num < t2.num实现相同两队只比一次 代码实现&#xff1a; with t as (SELECT team_name,caseteam_nameWHEN 勇士 then 1WHEN 湖人 then 2WHEN 灰熊 then 3else 4end numFROM team )SELECT t1.team_…

零经验想跳槽转行网络安全,需要准备什么?

最近在后台看到很多私信都是有关转行网络安全的问题&#xff0c;目前咨询最多的都是&#xff1a;觉得现在的工作没有发展空间&#xff0c;替代性强&#xff0c;工资低&#xff0c;想跳槽转行网络安全。其中&#xff0c;他们主要关心的是&#xff1a;没有经验怎么学习&#xff1…

模糊测试面面观 | 电动汽车充电桩安全漏洞案例分享

在上一期我们讲了针对车载以太网DOIP协议详细阐释在实际过程的漏洞发掘过程&#xff0c;本期我们将继续延展&#xff0c;探讨电动车充电系统的安全漏洞。开源网安在基于 GB/T 27930-2015通信标准的电动汽车充电桩中&#xff0c;采用渗透测试、模糊测试和数据流分析等多种安全漏…

易天光通信推出100G BIDI ER光模块最新解决方案

随着数字信息时代的快速发展&#xff0c;网络通信技术的迅猛进步成为推动科技创新和产业升级的重要引擎之一。作为光通信行业的新秀&#xff0c;近期易天光通信推出了全新的100G BIDI ER1 Lite光模块和100G BIDI LR1 Lite光模块&#xff0c;助力崭新的未来网络建设。 易天光通…

45.复购率问题求解

思路分析&#xff1a; &#xff08;1&#xff09;近xx天&#xff0c;最大日期肯定就是最新的一天&#xff0c;故先用max(order_date) over() today计算当天日期 &#xff08;2&#xff09;过滤出最近90天的订单并且按照user_id,product_id分组求购买次数&#xff1b; &#xff…

逐字稿 | 视频理解论文串讲(上)【论文精读】

大家好&#xff0c;前两期我们讲了视频理解领域里的两篇经典的论文&#xff0c;一个是双流网络&#xff0c;第一个是 I3D 网络&#xff0c;所以说对视频理解这个问题有了个基本的了解。 那今天我们就从 2014 年开始&#xff0c;一直到最近 2021 年的工作&#xff0c;我们一起来…

攻防世界题目练习——Web引导模式(三)(持续更新)

题目目录 1. mfw2.3.4.5. 1. mfw 进去看到网页和页面内容如下&#xff1a; 看到url的参数 ?pageabout &#xff0c;我以为是文件包含什么的&#xff0c;反复试了几次&#xff0c;想用 …/…/…/…/etc/passwd &#xff0c;但是发现.似乎被过滤了&#xff0c;实在不知道怎么做…

转行学网络安全,月薪6k到30k,给兄弟们一些个人建议

前言&#xff1a; 网络安全是指网络系统的硬件、软件及其系统中的数据受到保护&#xff0c;不因偶然或恶意原因而遭受破坏、更改、泄露&#xff0c;系统连续可靠正常地运行&#xff0c;网络服务不中断。 截至2018年8月&#xff0c;我国网民规模达8.02亿人&#xff0c;互联网高…

PHP 生成微信小程序码,并存储图片

背景 当前鄙人接手的项目&#xff0c;需要在设备机器上展示 小程序二维码 为了记录扫码用户从哪台机器注册的 那么&#xff0c;实现方案就是&#xff1a;在小程序码中&#xff0c;绑定设备编号参数 在此&#xff0c;记录一番实现步骤 … 小程序开发文档 - 【 获取不限制的小程…

数据结构-----红黑树简介

目录 前言 1.什么是红黑树&#xff1f; 2.为什么需要红黑树&#xff1f;&#xff08;与AVL树对比&#xff09; 3.红黑树的特性 前言 在此之前我们学习过了二叉排序树和平衡二叉树&#xff08;AVL树&#xff09;&#xff0c;这两种树都是属于搜索树的一种&#xff0c;那么今天…

计算机毕业设计 无人智慧超市管理系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

FSM人物动画状态机

人物动画状态机 介绍FSM角色模型的设置角色动作的设置角色动画控制器的设置书写角色动画的具体状态&#xff0c;实现缓动起步的FSM总结 介绍 摇杆我就不介绍了&#xff0c;之前我在这里面讲过怎么用摇杆&#xff0c;摇杆连接。 这里我先说下什么是FSM人物动画状态机&#xff0…

文心一言 VS 讯飞星火 VS chatgpt (114)-- 算法导论10.2 7题

七、用go语言&#xff0c;给出一个 O(n)时间的非递归过程&#xff0c;实现对一个含 n个元素的单链表的逆转。要求除存储链表本身所需的空间外&#xff0c;该过程只能使用固定大小的存储空间。 文心一言&#xff1a; 在Go语言中&#xff0c;你可以使用迭代方法来反转一个单链表…

【C++】:string用法详解

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux的基础知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

算法通过村第十四关-堆|黄金笔记|中位数

文章目录 前言数据流中的中位数的问题总结 前言 提示&#xff1a;我独自度过了太多的时光&#xff0c;沉默已成一种习惯。 帕瑞尔马卡姆《夜航西飞》 这个是一个比较难的题目&#xff0c;要不尝试一下看看。 数据流中的中位数的问题 参考题目地址&#xff1a;295. 数据流的中位…

身为程序员,你很有必要了解一下JNPF

一、JNPF是什么&#xff1f; JNPF是一个“低代码”的可视化编程平台&#xff0c;采用J2EE技术体系&#xff0c;基于Spring Boot框架封装的快速开发平台&#xff0c;包含多种开箱即用的功能&#xff0c;具备RBAC、自动生成代码、SaaS多租户等多个功能和模块。 JNPF&#xff0c;重…

真人现在猫鼠躲猫猫游戏搭建流程:专业思考与深度思考

真人现在猫鼠躲猫猫游戏是种充满乐趣和挑战的团队竞技游戏。本文将从游戏规则设计、场地布置、技术实现和用户体验等方面&#xff0c;深入探讨人现在猫鼠躲猫猫游戏的搭建流程&#xff0c;并结合专业思考与深度思考&#xff0c;为游戏搭建提供全面指导。 一、游戏规则设计&…

【uboot】Uboot的启动流程

引言 在驱动岗位上&#xff0c;每一位新员工刚入职期间都需要理解和掌握uboot&#xff0c;但深入的理解代码往往需要耗费大量的时间去反复阅读。本文希望对uboot进行尽可能详细的解析&#xff0c;帮助其他人更快的掌握和理解uboot源码。 准备工作 uboot源码 本文是基于Hi35…