String str=new String(“tango“) 创建了几个对象?
面试回答
创建的对象数 应该是1个或者2个。
首先要清楚什么是对象?
Java 是一种面向对象的语言,而 Java 对象在 JVM 中的存储也是有一定的结构的,在 HotSpot 虚拟机中,存储的形式就是 oop-klass model,即 Java 对象模型。我们在 Java 代码中,使用 new 创建一个对象的时候,JVM 会创建一个 instanceOopDesc 对象,这个对象中包含了两部分信息,对象头以及元数据。对象头中有一些运行时数据,其中就包括和多线程相关的锁的信息。元数据其实维护的是指针,指向的是对象所属的类的 instanceKlass。
这才叫对象。其他的,一概都不叫对象。
那么不管怎么样,一次 new 的过程,都会在堆上创建一个对象,那么就是起码有一个对象了。至于另外一个对象,到底有没有要看具体情况了。
另外这一对象就是常量池中的字符串常量,这个字符串其实是类编译阶段就进到 Class 常量池的,那么当这个类第一次被 ClassLoader 加载的时候,会从 Class 常量池进入到运行时常量池。
在运行时常量池中,也并不是会立刻被解析成对象,而是会先以 JVM_CONSTANT_UnresolveString_info 的形式驻留在常量池。在后面,该引用第一次被 LDC 指令执行到的时候,就尝试在堆上创建字符串对象,并将对象的引用驻留在字符串常量池中。
通过看上面的过程,你也能发现,这个过程的触发条件是我们没办法决定的,问题的题干中也没有提到。有可能执行这段代码的时候是第一次 LDC 指令执行,也许在前面就执行过了。
所以,如果是第一次执行,那么就是会同时创建两个对象。一个字符串常量引用指向的对象,一个我们 new 出来的对象。
如果不是第一次执行,那么就只会创建我们自己 new 出来的对象。
至于有人说什么在字符串池内还有在栈上还有一个引用对象,你听听这说法,引用就是引用。别往对象上面扯。
知识扩展
字面量和运行时常量池
JVM 为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。为了减少在 JVM 中创建的字符串的数量,字符串维护了一个字符串常量池。
在 JVM 运行时区域的方法区中,有一块区域是运行时常量池,主要用来存储编译器生成的各种字面量和符号引用。
intern
编译器生成的各种字面量和符号引用是运行时常量池中比较重要的一部分来源,但是并不是全部。那么还有一种情况,可以在运行期间运行时常量池中添加常量。那就是 String
的 intern
方法。
当一个 String
实例调用 intern()
方法时,Java 查找常量池中是否有相同 Unicode 的字符串常量,如果有,则返回其的引用,如果没有,则在常量池增加一个 Unicode 等于 str 的字符串并返回它的引用。
intern() 有两个作用,第一个是将字符串字面量放入常量池(如果池没有的话),第二个是返回这个常量的引用。
intern 的正确用法
不知道,你有没有发现,在 String s = new String("Tango").intern();
中,其实 intern
是多余的?
因为就算不用 intern
, Tango 作为一个字面量也会被加载到 Class 文件的常量池,进而加入到运行时常量池中,为啥还要多此一举呢?到底什么场景下才需要使用 intern
呢?
在解释这个之前,我们先来看下代码:
String s1="Tango";String s2="Chi";String s3=s1+s2;String s4="Tango"+"Chi";
在经过反编译后,得到代码如下:
String s1 = "Tango";String s2 = "Chi";String s3 = (new StringBuilder()).append(s1).append(s2).toString();String s4 = "TangoChi";
可以发现,同样是字符串拼接,s3和s4在经过编译器编译后的实现方式并不一样。s3被转化成 StringBuilder
及 append
,而 s4 被直接拼接成新的字符串。
如果你感兴趣,你还能发现,String s3 = s1 + s2;
经过编译之后,常量池中是有两个字符串常量的分别是 Tango
、Chi
(其实 Tango
和 Chi
是 String s1="Tango";
和 String s2="Chi";
定义出来的),拼接结果 TangoChi
并不在常量池中。
如果代码只有 String s4 = "Tango" + "Chi";
,那么常量池中将只有 TangoChi
而没有 Tango
和 Chi
。
究其原因,是因为常量池要保存的是已确定的字面量值。也就是说,对于字符串的拼接,纯字面量和字面量的拼接,会把拼接结果作为常量保持到字符串池。
如果在字符串拼接中,有一个参数是非字面量,而是一个变量的话,整个拼接操作会被编译成 StringBuilder.append
,这种情况编译器是无法知道其确定值的。只有在运行期才确定。
那么,有了这个特性了,intern
就有了用武之地了。那就是很多时候,我们在程序中得到的字符串只有在运行期才能确定的,在编译期是无法确定的,那么也就没办法在编译期被加入到常量池中。
这时候,对于那种可能经常使用的字符串,使用 intern
进行定义,每次 JVM 运行到这段代码的时候,就会直接把常量池该字面值的引用返回,这样就可以减少大量字符串对象的创建了。
如一深入解析 String#intern 文中举的一个例子:
static final int Max = 1000 * 100000;static final String[] arr = new String[Max];public static void main(String[] args) {Integer [] DB_DATA=new Integer[10];Random random=new Random(10*10000);for (int i = 0; i < DB_DATA.length;i++) {DB_DATA[i]=random.nextInt();}long t=System.currentTimeMillis();for (int i = 0; i < Max; i++) {arr[i]=new String(String.valueOf(DB_DATA[i%DB_DATA.length])).intern();}System.out.println(System.currentTimeMillis()-t+"ms");System.gc();}
在以上代码中,我们明确的知道,会有很多重复的相同的字符串产生,但是这些字符串的值都是只有在运行期才能确定的。所以,只能我们通过 intern
显示的将其加入常量池,这样可以减少很多字符串的重复创建。
相关文章:
String str=new String(“tango“) 创建了几个对象?
面试回答 创建的对象数 应该是1个或者2个。 首先要清楚什么是对象? Java 是一种面向对象的语言,而 Java 对象在 JVM 中的存储也是有一定的结构的,在 HotSpot 虚拟机中,存储的形式就是 oop-klass model,即 Java 对象模型…...

引入三阶失真的非线性放大器的模拟输出及使用中值滤波器去除峰值研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

【观察者设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
简介 观察者模式(Observer Pattern)是一种行为型模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 观察者模式使用三个类Subject、Observer和Client。Subject…...
精细解析中文公司名称:智能分词工具助力地名、品牌名、行业词和后缀提取
精细解析中文公司名称:智能分词工具助力地名、品牌名、行业词和后缀提取 中文公司名称分词工具,支持公司名称中的地名,品牌名(主词),行业词,公司名后缀提取。 对公司名文本解析,识…...

网络编程(JavaEE初阶系列10)
目录 前言: 1.网络编程的基础 1.1为什么需要网络编程 1.2什么是网络编程 1.3网络编程中的基本概念 1.3.1发送端和接收端 1.3.2请求和响应 1.3.3客户端和服务端 2.Socket套接字 2.1概念 2.2分类 3.UDP数据报套接字编程 3.1DataGramSocket API 3.2Datagr…...
Git常用的指令
Git常用的指令 OMMP提交代码的流程 0、配置: git config --list 查看当前配置 git congig --global user.name user 这个会显示你的提交到git的名字 格式:git config [–local|–global|–system] –unset section.key 格式:git config [–l…...

LoadRunner(2)
一、Controller 1.1场景设计 1.通过VUG打开 施压机器:发起请求的角色(用户本地电脑) 被压机器:处理请求的角色(服务器) 2.直接双击Controller 场景设计:需要关注三个部分 第一部分: 第二部分: 2.1运行场景…...

CTF之逆向之阿里巴巴
题目地址:http://www.shiyanbar.com/ctf/13 题目预览: 解题过程: 1、下载附件发现是exe文件 2、使用PEid和Detect It Easy查壳 和 开发语言,发现没有加壳,都是用C#开发的 3、C#和Java Python属于解释型语言ÿ…...

Labview控制APx(Audio Precision)进行测试测量(五)
驱动程序 VIs如何处理配置设置中的单元 APx500 应用程序具有复杂的控件,具有以下功能: 数值和单位组合在一个控制中(例如,1.000 Vrms ) •值转换为 SI 格式(例如,1.000 mVrms 或 1.000 μVrms) •单位之间的转换发生在控制(例如,V…...

在单元测试中使用Jest模拟VS Code extension API
对VS Code extension进行单元测试时通常会遇到一个问题,代码中所使用的VS Code编辑器的功能都依赖于vscode库,但是我们在单元测试中并没有添加对vscode库的依赖,所以导致运行单元测试时出错。由于vscode库是作为第三方依赖被引入到我们的VS C…...

django boostrap html实现可拖拽的左右布局,鼠标拖动调整左右布局的大小或占比
一、实现的效果 最近需要在Django项目中,实现一个左右布局的html页面,页面框架使用的是boostrap。但这个布局不是简单的左右分栏布局,而是需要实现可以通过鼠标拖拽的方式动态调整左右两侧布局的大小和占比。效果大致如下: 一开始,页面分为左右两块布局: 鼠标放到中间的…...

谈谈闭包和闭包使用场景
一、什么是闭包 概念:闭包还是作用域的一种特殊应用 二、触发闭包的情况 1.函数当做返回值被返回 2.函数当做参数被传递 3.自执行匿名函数 //情况1:函数当做返回值被返回 function fn(){const a 1;return function(){console.log(a) //1}; } const a …...
MATLAB算法实战应用案例精讲-【图像处理】边界框锚框
目录 目标检测 应用场景 目标检测发展历程 常用数据集 边界框(bounding box)...
04什么场景要用到微服务
一句话导读 根据微服务的特点,可以总结为在构建复杂的、大型的、分布式的、高可用、高并发、高性能的应用时可以使用微服务架构。 目录 一句话导读 一、微服务适用场景 1.业务复杂,模块多且相对独立 2.团队多,管理隔离 3.应用规模大&#…...

.NET SqlSuger 简单介绍,超快开发数据库
文章目录 前言SqlSugar使用我的环境Nuget 安装新建连接串DB First 和 Code First使用增删改查 总结 前言 我之前介绍过EFCore 怎么使用Nuget快速创建数据库,我之后发现SqlSugar更快。这里简单再说一下SqlSugar如何使用 .NET Core 数据库DB First自动生成࿰…...
SpringBoot复习:(28)【前后端不分离】自定义View
一、自定义View package cn.edu.tju.view;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Comp…...

springcloud3 springcloud stream的学习以及案例(了解)
一 springcloud stream的作用 1.1 springcloud stream作用 stream屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型。 stream中的消息通信模式遵循了“发布-订阅”模式。 1.2 Binder作用 通过定义绑定器Binder作为中间层,实现…...
Kotlin理解内置函数
目录 一 内置函数1.1 apply 函数1.2 let 函数1.3 run函数1.4 with函数1.5 also函数1.6 takeIf函数1.7 takeUnless函数1.8 总结 Kotlin内置函数包括:let、run、with、apply、also,这些函数都是在Any类中定义的扩展函数,所以任何对象都可以调用…...

手机app测试
一、安装、卸载、更新、运行 1.安装、卸载 应用是否可以正常安装(命令行安装;apk/ipa安装包安装)(有网,无网是否都正常)卸载过程中出现死机,断电,重启等意外的情况&…...
Centos部署Git
Centos部署Git 文章目录 Centos部署Git部署步骤初始化配置免登录 部署步骤 初始化 -- 安装git yum install git配置免登录 配置git下载代码时 每次都需要输入密码的事情 -- 生成 gitconfig 文件 git config --global credential.helper store -- 配置登录邮箱 git config …...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...