《你并不了解 String》 勘误

2024-02-17 21:32
文章标签 string 了解 勘误

本文主要是介绍《你并不了解 String》 勘误,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写技术文章其实是个很好的学习方式。首先你得自己摸清楚原理,然后才能尝试去表达出来。你写出来的东西,别人看了,给予你反馈,也是一个互相学习的过程。这不,前几天碰到一个读者提出的一个问题,让我发现了自己文章中的一个疏漏,下面就来说说这个问题。

在我之前的一篇文章 你并不了解 String 中出了这样一道题目:

String str1 = new String("j") + new String("ava"); // 1
str1.intern(); // 2
String str2 = "java"; // 3
System.out.println(str1 == str2); // 4

看一遍,想一遍,如果还不能准确给出答案的话可以再仔细看看我的那篇文章。正常情况下,答案应该是 true。贴一下之前的讲解:

经过编译,j 、ava 和 java 进入 Class 常量池 中。 类加载阶段并不会创建实例,驻留字符串常量池。到运行期,第一行代码中会创建 j 、ava 实例并驻留常量池,+ 会被 JVM 自动优化为 StringBuilder ,拼接出 java 字符串,将 str1 指向该字符串实例。需要注意的是,这里不会将 java 驻留到常量池。第二行代码调用了 intern(),由于此时常量池中没有 java,所以将 str1 的引用存入了常量池。第三行代码,ldc 指令发现常量池中就有 java,直接返回常量池中其对应的引用,并赋给 str2。所以 str1 和 str2 是相等的。

看起来说的还是挺有道理的,我自己放到 IDEA 中执行也的确是 true。但是有一位读者给我评论说他执行下来是 false。我的第一反应就是 “我的代码肯定没错,应该是他写错了” ,就加了这兄弟的微信,截图给我看了看代码。然后我就蒙了,果然是 false。同样的代码,却是不同的执行结果。

那么,究竟 str1str2 为什么会不相等呢?

我们再来分析一下代码,第一行:

String str1 = new String("j") + new String("ava"); // 1

从这句话中可以肯定的是,str1 指向堆中的一个 java 字符串实例,且这个字符串是在堆中新创建的。再看第二和第三行:

str1.intern(); // 2
String str2 = "java"; // 3

str1.intern()str1 是指向堆中的一个 java 字符串实例的,调用 intern() 的话,此时就有两种情况:

  1. 字符串常量池中没有 java 字符串的引用
  2. 字符串常量池中已经有了 java 字符串的引用

第一种情况,就是我上篇文章中的分析,str1 驻留到字符串常量池,结果是 true。第二种情况,字符串常量池中已经有了 java,此时再执行 str1.intern() 就会直接返回字符串常量池中 java 字符串对应的引用,并不会将 str1 驻留到字符串常量池。String str2 = "java"; 一执行,str2 等于字符串常量池中的 java 对应的引用。而 str1 是新建在堆中的 java 字符串的引用,自然而然,比较结果是 false

这么分析下来,这位读者无疑是第二种情况了。但是为什么同样在 main() 方法中直接执行这几行代码,结果会不一样呢?为什么 main() 方法中的代码还没有执行,字符串常量池中就已经有 java 字符串的引用了呢?

对啊,为什么会这样呢?等等,java,这个字符串是不是有点特殊。我尝试着让这位读者换一个特殊点的字符串再运行一次,竟然还让我蒙对了,这下打印 true 了。看到这里,你应该明白了,在 JVM 启动的过程中,字符串常量池已经在发挥作用了,在 main() 方法运行之前,一些字符串引用已经驻留在字符串常量池,比如上面的 java,但也不是百分之百的,我手里的 Ubuntu 18.04 就一直打印的是 true,你们也可以掏出电脑来试一试。

对于 String.intern() 方法,我们只需要搞清楚当前字符串常量池是否已经驻留该字符串引用,已驻留和未驻留将导致不同的执行逻辑。

  • 已驻留,直接返回字符串常量池中的引用
  • 未驻留,将当前字符串引用驻留进字符串常量池并返回该引用

这么一来,我和这位读者都彻彻底底的搞清楚了 intern() 方法,下次再遇到类似的面试题应该都不是问题了。所以呢,也欢迎大家多多提出自己的评论和想法,可以在掘金文章评论,可以微信搜索 秉心说 或者扫描文末二维码关注公众号私信我,也可以直接加我微信 bingxinshuo_ ,微信后台回复 秉心说 也可以加我微信。力所能及的问题我都会尽量解答。

文章越写越短了,走进 JDK 系列好久不出新文章了,主要是最近输出大于输入,白天要上班,晚上还要奶孩子,每次文章大概都是十二点左右发出来的。不过好在最近的文章阅读量都还不错,也才有了写下去的动力。

大家也可以关注我的公众号 “秉心说”,这个名字的由来,其实很简单,就是我女儿的名字。“秉心识本源,于事少凝滞”,也是我的公众号自动回复的一句话,既是对孩子的期许,也是对自己的期许,也希望大家都可以做到 秉持内心,保持本源。(大白话翻译一下,就是别忘了自己是个程序猿!)

说了一些题外话,后续还是会继续保持输入和输出,专注 Java/Android 原创知识分享,不妨点个赞再走吧!

文章首发于微信公众号: 秉心说 , 专注 Java 、 Android 原创知识分享,LeetCode 题解,欢迎关注!

这篇关于《你并不了解 String》 勘误的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/719045

相关文章

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

PHP: 深入了解一致性哈希

前言 随着memcache、redis以及其它一些内存K/V数据库的流行,一致性哈希也越来越被开发者所了解。因为这些内存K/V数据库大多不提供分布式支持(本文以redis为例),所以如果要提供多台redis server来提供服务的话,就需要解决如何将数据分散到redis server,并且在增减redis server时如何最大化的不令数据重新分布,这将是本文讨论的范畴。 取模算法 取模运

Weex入门教程之1,了解Weex

【资料合集】Weex Conf回顾集锦:讲义PDF+活动视频! PDF分享:链接:http://pan.baidu.com/s/1hr8RniG 密码:fa3j 官方教程:https://weex-project.io/cn/v-0.10/guide/index.html 用意 主要是介绍Weex,并未涉及开发方面,好让我们开始开发之前充分地了解Weex到底是个什么。 以下描述主要摘取于

Java了解相对较多!

我是对Java了解相对较多,而对C#则是因工作需要才去看了一下,C#跟Java在语法上非常相似,而最初让我比较困惑的就是委托、事件部分,相信大多数初学者也有类似的困惑。经过跟Java的对比学习,发现这其实跟Java的监听、事件是等同的,只是表述上不同罢了。   委托+事件是观察者模式的一个典型例子,所谓的委托其实就是观察者,它会关心某种事件,一旦这种事件被触发,这个观察者就会行动。   下

使用WebP解决网站加载速度问题,这些细节你需要了解

说到网页的图片格式,大家最常想到的可能是JPEG、PNG,毕竟这些老牌格式陪伴我们这么多年。然而,近几年,有一个格式悄悄崭露头角,那就是WebP。很多人可能听说过,但到底它好在哪?你的网站或者项目是不是也应该用WebP呢?别着急,今天咱们就来好好聊聊WebP这个图片格式的前世今生,以及它值不值得你花时间去用。 为什么会有WebP? 你有没有遇到过这样的情况?网页加载特别慢,尤其是那

初步了解VTK装配体

VTK还不太了解,根据资料, vtk.vtkAssembly 是 VTK库中的一个重要类,允许通过将多个vtkActor对象组合在一起来创建复杂的3D模型。 import vtkimport mathfrom vtk.util.colors import *filenames = ["cylinder.stl","sphere.stl","torus.stl"]dt = 1.0renW

hdu2072(string的应用)

单词数 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 25447    Accepted Submission(s): 5957 Problem Description lily的好朋友xiaoou333最近很空,他

Post-Training有多重要?一文带你了解全部细节

1. 简介 随着LLM学界和工业界日新月异的发展,不仅预训练所用的算力和数据正在疯狂内卷,后训练(post-training)的对齐和微调方法也在不断更新。InstructGPT、WebGPT等较早发布的模型使用标准RLHF方法,其中的数据管理风格和规模似乎已经过时。近来,Meta、谷歌和英伟达等AI巨头纷纷发布开源模型,附带发布详尽的论文或报告,包括Llama 3.1、Nemotron 340