Java字符串常量池以及new String(“abc“)到底创建了几个对象?各种字符串到底相不相等?

news2024/11/15 23:44:30

new String(“abc”)到底创建了几个对象?

字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建

1.如果字符串常量池中不存在“abc”的引用,则先在字符串常量池中创建,然后在堆空间中创建,总共创建2个字符串对象。

2.如果字符串常量池中存在字符串对象“abc”的引用,则在堆中创建1个字符串对象。
在这里插入图片描述

接下来我们通过一些例子理解字符串到底是怎么创建的以及字符串间是否相等:
1.

String s1 = "abc"; // 常量池
String s2 = new String("abc"); // 堆
System.out.println(s1 == s2);

答案:false。s1是字符串常量池的对象,s2是堆中的对象。

String s1 = "a" + "b"; // 常量池
String s2 = "ab"; // 常量池
System.out.println(s1 == s2);

答案:true。s1中由于"a"和"b"都是常量,在编译期就会对其进行优化,等价于"ab",s1和s2都是同一个字符串常量池中的对象。

String s1 = "a" + new String("b"); // new String(),堆
String s2 = "ab"; // 常量池
System.out.println(s1 == s2);
String s1 = new String("a") + new String("b"); // new String(),堆
String s2 = "ab"; // 常量池
System.out.println(s1 == s2);
String x1 = "a"; // 常量池
String x2 = "b"; // 常量池
String s1 = x1 + x2; // new String(),堆
String s2 = "ab"; // 常量池
System.out.println(s1 == s2);

答案:都为false。这三个例子中s1都是动态拼接字符串,等价于new StringBuilder().append(“a”).append(“b”).toString() <=> new String(“ab”),本质上还是new了一个对象,而s2是字符串常量池中的对象,因此不相等。

  1. jdk1.8版本
String s1 = new String("a") + new String("b"); // 堆
// 此时常量池中有["a","b"],注意并没有"ab",因为动态拼接并不会在常量池中创建对象。

String s2 = s1.intern(); // s2为常量池中的“ab”,由于常量池中没有"ab",创建一个"ab",并且这个"ab"的引用与s1相同。
// 此时常量池中有["a","b","ab"],其中"ab"的引用为s1的引用
System.out.println(s1 == "ab"); // 是同一个引用
System.out.println(s2 == "ab"); // s2就是常量池中的"ab",显然为true

答案:true,true。首先intern方法返回的是常量池中的对象,在jdk1.8中分两种情况:
1.如果s1的字面量在字符串常量池中存在,则直接返回常量池中的对象。
2.如果不存在,在常量池中创建一个对象,该对象保存s1字符串的引用并返回。也就是说此时堆中的s1和常量池中的s1是同一个引用。

5.jdk1.8版本

String x = "ab"; // 常量池
// 此时常量池中有["ab"]

String s1 = new String("a") + new String("b"); // 堆
// 此时常量池中有["a","b","ab"]
String s2 = s1.intern(); // 常量池
// 由于常量池中已经有"ab"了,直接返回常量池中的"ab",此时常量池的"ab"和s1的引用并不是同一个。
System.out.println(s1 == x); 
System.out.println(s2 == x); 

答案:false, true。intern方法中的第一种情况,s1和x分别来自堆和常量池,且不是同一个引用,为false,s2和x都来自常量池,为true。

6.jdk1.6版本

String x = "ab"; // 常量池
// 此时常量池中有["ab"]

String s1 = new String("a") + new String("b"); // 堆
// 此时常量池中有["a","b","ab"]
String s2 = s1.intern(); // 常量池
// 由于常量池中已经有"ab"了,直接返回常量池中的"ab",此时常量池的"ab"和s1的引用并不是同一个。
System.out.println(s1 == x); 
System.out.println(s2 == x); 

答案:false,true。
在jdk1.6中,如果字符串常量池有这个字符串,会和1.8一样,直接返回常量池中的字符串,如果字符串常量池中没有这个字符串,会把字符串对象复制一份放入串池,也就是说常量池和堆中的对象引用不是同一个。

7.jdk1.6版本


String s1 = new String("a") + new String("b"); // 堆
// 此时常量池中有["a","b"]
String s2 = s1.intern(); // 常量池
// 此时常量池中有["a","b","ab"]
// 由于1.6版本intern是复制s1,因此s1依旧在堆中,s2在常量池中,不是同一个引用
System.out.println(s1 == "ab"); 
System.out.println(s2 == "ab"); 

答案:false,true。

再来看下面这个例子:

String s1 = "Java"; // 常量池
String s2 = s1.intern(); // 常量池
String s3 = new String("Java"); // 堆
String s4 = s3.intern(); // 常量池
System.out.println(s1 == s2); // true
System.out.println(s3 == s4); // false
System.out.println(s1 == s4); // true

s1==s2显然为true,s1 == s4显然也为true,因为s2和s4都是常量池中的"Java",s3和s4不相等,因为s3.intern()中在常量池中已经有"Java"了,直接把常量池中的"Java"返回给s4,而s3不做任何变动。

总结:

  1. 存放位置
  • 字面量(双引号引的)放在字符串常量池中,new出来的对象都放在堆中。
  1. 字符串拼接
  • 如果两个字符串都是直接用双引号引的,拼接时在编译期就会对其进行优化,例如String s = “a” + "b"会直接优化为String s = “ab”,这样创建出来的对象在常量池中。
  • 字符串动态拼接时,例如String s = “a” + new String(“b”),String s = new String(“a”) + new String(“b”),String s = x + y,本质上是调用了StringBuilder中的append方法,最后使用toString()转换为String类型,这样创建出来的对象在中,并且不会像new String(“abc”)一样去常量池中创建一个字符串。
  1. intern()方法返回的是常量池中的对象
  • 如果是JDK1.8:
    • 如果s1的字面量在字符串常量池中存在,则直接返回常量池中的对象。
    • 如果不存在,在常量池中创建一个对象,该对象保存s1字符串的引用并返回。也就是说此时堆中的s1和常量池中的s1是同一个引用。
    • 可以理解为如果常量池中不存在就将堆中的对象移动到常量池中。
  • 如果是JDK1.6:
    • 如果s1的字面量在字符串常量池中存在,则直接返回常量池中的对象。
    • 如果不存在,在常量池中复制一份s1字符串,s1的引用和常量池中的引用不是同一个。
    • 可以理解为如果常量池中不存在就将堆中的对象复制到常量池中。

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

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

相关文章

GD32F103VE外部中断

GD32F103VE外部中断线线0~15&#xff0c;对应外部IO口的输入中断。它有7个中断向量&#xff0c;外部中断线0 ~ 4分别对应EXTI0_IRQn ~ EXTI4_IRQn中断向量&#xff1b;外部中断线 5 ~ 9 共用一个 EXTI9_5_IRQn中断向量&#xff1b;外部中断线10~15 共用一个 EXTI15_10_IRQn中断…

深入探索Vue.js核心技术与跨平台开发uni-app实战

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 前言 在当今Web应用不断…

小程序商城免费搭建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全景+b2b2c bbc

​ 1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前…

7、Kubernetes核心技术 - Secret

目录 一、Secret概述 二、Secret 三种类型 2.1、Opaque 2..2、kubernetes.io/dockerconfigjson 2.3、kubernetes.io/service-account-token 三、Secret创建 3.1、命令行方式创建 Secret 3.2、yaml方式创建 Secret 四、Secret解码 五、Secret使用 5.1、将 Secret 挂载…

Mybatis实现JsonObject对象与JSON之间交互

项目中使用PostGresql数据库进行数据存储&#xff0c;表中某字段为Json类型&#xff0c;用于存储Json格式数据。PG数据库能够直接存储Json算是一大特色&#xff0c;很多特定情境下使用直接存储Json字段数据能够大量节省开发时间&#xff0c;提高后台数据查询和转换效率。 1、基…

第三章 图论 No.1单源最短路及其综合应用

文章目录 1129. 热浪1128. 信使1127. 香甜的黄油1126. 最小花费920. 最优乘车903. 昂贵的聘礼1135. 新年好340. 通信线路342. 道路与航线341. 最优贸易 做乘法的最短路时&#xff0c;若权值>0&#xff0c;只能用spfa来做&#xff0c;相等于加法中的负权边 1129. 热浪 1129.…

Spring接口ApplicationRunner的作用和使用介绍

在Spring框架中&#xff0c;ApplicationRunner接口是org.springframework.boot.ApplicationRunner接口的一部分。它是Spring Boot中用于在Spring应用程序启动完成后执行特定任务的接口。ApplicationRunner的作用是在Spring应用程序完全启动后&#xff0c;执行一些初始化任务或处…

W6100-EVB-PICO做DNS Client进行域名解析(四)

前言 在上一章节中我们用W6100-EVB-PICO通过dhcp获取ip地址&#xff08;网关&#xff0c;子网掩码&#xff0c;dns服务器&#xff09;等信息&#xff0c;给我们的开发板配置网络信息&#xff0c;成功的接入网络中&#xff0c;那么本章将教大家如何让我们的开发板进行DNS域名解…

python二级用哪个版本的软件,二级python用哪个版本

大家好&#xff0c;给大家分享一下python二级用哪个版本的软件&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; Python开发软件可根据其用途不同分为两种&#xff0c;一种是Python代码编辑器&#xff0c;一种是Python集成开发工具&#xff…

Mac显示隐藏文件夹

1、设置隐藏文件可见 defaults write com.apple.finder AppleShowAllFiles TRUE 2、killall Finder killall Finder

H3C交换机如何清除接口配置信息

环境&#xff1a; H3C S6520-26Q-SI 问题描述&#xff1a; H3C交换机如何清除接口配置信息 解决方案&#xff1a; 在接口下使用default命令 [H3C-Ten-GigabitEthernet1/0/3]dis th # interface Ten-GigabitEthernet1/0/3port link-mode bridgeport link-type trunkport tr…

linux的搭建以及网关配置

Linux 目前国内 Linux 更多的是应用于服务器上,而桌面操作系统更多使用的是 Windows 安装linux虚拟机 网址 VMware下载网址 点击Workstation 16 Pro for Windows下载 安装CentOS centO下载网址 依次点击 7.6.1810/ isos/ x86_64/ CentOS-7-x86_64-DVD-1810.…

面试热题(前中序遍历构建树)

给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 题目中是给定两个数组&#xff0c;一个是存放这颗树的前序遍历的数组&#xff0c;一个是存放这棵树的…

一个严肃的话题,ADR会取代WAF和RASP吗?

做安全的人应该都对WAF耳熟能详&#xff0c;也就是我们常说的Web应用防火墙&#xff0c;成为了应用安全防护的明星产品之一。从传统的防火墙、IDS、IPS&#xff0c;再到WAF横空出世&#xff0c;引领技术趋势若干年&#xff0c;这一阶段可以称为应用安全防护1.0时代。作为一款成…

通过华为杯竞赛、高教社杯和数学建模国赛实现逆袭;助力名利双收

文章目录 ⭐ 赛事介绍⭐ 参赛好处⭐ 辅导比赛⭐ 写在最后 ⭐ 赛事介绍 华为杯全国研究生数学建模竞赛是由华为公司主办的一项面向全国研究生的数学建模竞赛。该竞赛旨在通过实际问题的建模和解决&#xff0c;培养研究生的创新能力和团队合作精神&#xff0c;推动科技创新和应用…

深度解析线程池的文章

java 系统的运行归根到底是程序的运行&#xff0c;程序的运行归根到底是代码的执行&#xff0c;代码的执行归根到底是虚拟机的执行&#xff0c;虚拟机的执行其实就是操作系统的线程在执行&#xff0c;并且会占用一定的系统资源&#xff0c;如CPU、内存、磁盘、网络等等。所以&a…

IPsec简介

IPsec简介 IPsec&#xff08;IP Security&#xff09;是IETF制定的三层隧道加密协议&#xff0c;它为Internet上传输的数据提供了高质量的、可互操作的、基于密码学的安全保证。特定的通信方之间在IP层通过加密与数据源认证等方式&#xff0c;提供了以下的安全服务&#xff1a…

xml的注释删要干净Parameter index out of range (2 > number of parameters, which is 1).

报了这个bugjava.sql.SQLException: Parameter index out of range (2 > number of parameters, which is 1). 对应sql语句是这样的 把注释删掉&#xff0c;就不报错了&#xff0c;这是什么奇葩bug

2023年电赛---运动目标控制与自动追踪系统(E题)发挥题思路

前言 &#xff08;1&#xff09;因为博客编辑字数超过1W字会导致MD编辑器非常卡顿。所以我将发挥题和基础题的思路拆开了。 &#xff08;2&#xff09;更新日记&#xff1a; <1>2023年8月4日&#xff0c;9点20分。分离发挥题思路和基础题思路&#xff0c;增加了博主Huiye…

结构体,枚举,联合大小的计算规则

目录 1.结构体大小的计算 补充&#xff08;位段&#xff09; 2.枚举的大小&#xff08;4个字节&#xff09; 3.联合大小的计算 1.结构体大小的计算 &#xff08;1&#xff09;结构体内存对齐的规则 1. 第一个成员在与结构体变量偏移量为 0 的地址处。 2. 其他成员变量要对…