面试进阶之字符串常量池

转载自  面试进阶之字符串常量池

作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池:

  • 字符串常量池的设计意图是什么?

  • 字符串常量池在哪里?

  • 如何操作字符串常量池?

 

字符串常量池的设计思想

a.字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能

b.JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化

  • 为字符串开辟一个字符串常量池,类似于缓存区

  • 创建字符串常量时,首先坚持字符串常量池是否存在该字符串

  • 存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中

c.实现的基础

  • 实现该优化的基础是因为字符串是不可变的,可以不用担心数据冲突进行共享

  • 运行时实例创建的全局字符串常量池中有一个表,总是为池中每个唯一的字符串对象维护一个引用,这就意味着它们一直引用着字符串常量池中的对象,所以,在常量池中的这些字符串不会被垃圾收集器回收

 

代码:从字符串常量池中获取相应的字符串

  String str1 = “hello”;String str2 = “hello”;System.out.printl("str1 == str2" : str1 == str2 ) //true

 

字符串常量池在哪里

在分析字符串常量池的位置时,首先了解一下堆、栈、方法区:

 

  • 存储的是对象,每个对象都包含一个与之对应的class

  • JVM只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身

  • 对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定

  • 每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象)

  • 每个栈中的数据(原始类型和对象引用)都是私有的

  • 栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)

  • 数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失

方法区

  • 静态区,跟堆一样,被所有的线程共享

  • 方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量

 

字符串常量池则存在于方法区

代码:堆栈方法区存储字符串

String str1 = “abc”;
String str2 = “abc”;
String str3 = “abc”;
String str4 = new String(“abc”);
String str5 = new String(“abc”);

 

 

字符串对象的创建

面试题:String str4 = new String(“abc”) 创建多少个对象?

1.在常量池中查找是否有“abc”对象

  • 有则返回对应的引用实例

  • 没有则创建对应的实例对象

2.在堆中 new 一个 String("abc") 对象

3.将对象地址赋值给str4,创建一个引用

所以,常量池中没有“abc”字面量则创建两个对象,否则创建一个对象,以及创建一个引用

根据字面量,往往会提出这样的变式题:

String str1 = new String("A"+"B") ; 会创建多少个对象? 

String str2 = new String("ABC") + "ABC" ; 会创建多少个对象?

str1:
字符串常量池:"A","B","AB" : 3个
堆:new String("AB") :1个
引用: str1 :1个
总共 : 5个

str2 :
字符串常量池:"ABC" : 1个
堆:new String("ABC") :1个
引用: str2 :1个
总共 : 3个


代码:基础类型的变量和常量,变量和引用存储在栈中,常量存储在常量池中

int a1 = 1;
int a2 = 1;
int a3 = 1;public static int INT1 =1 ;
public static int INT2 =1 ;
public static int INT3 =1 ;

 

操作字符串常量池的方式

JVM实例化字符串常量池时

  String str1 = “hello”;String str2 = “hello”;System.out.printl("str1 == str2" : str1 == str2 ) //true
String.intern()

通过new操作符创建的字符串对象不指向字符串池中的任何对象,但是可以通过使用字符串的intern()方法来指向其中的某一个。java.lang.String.intern()返回一个保留池字符串,就是一个在全局字符串池中有了一个入口。如果以前没有在全局字符串池中,那么它就会被添加到里面

   // Create three strings in three different ways.String s1 = "Hello";String s2 = new StringBuffer("He").append("llo").toString();String s3 = s2.intern();// Determine which strings are equivalent using the ==// operatorSystem.out.println("s1 == s2? " + (s1 == s2)); // falseSystem.out.println("s1 == s3? " + (s1 == s3)); // true

 

字面量和常量池初探

字符串对象内部是用字符数组存储的,那么看下面的例子:

String m = "hello,world";
String n = "hello,world";
String u = new String(m);
String v = new String("hello,world");

1.会分配一个11长度的char数组,并在常量池分配一个由这个char数组组成的字符串,然后由m去引用这个字符串

2.用n去引用常量池里边的字符串,所以和n引用的是同一个对象

3.生成一个新的字符串,但内部的字符数组引用着m内部的字符数组

4.同样会生成一个新的字符串,但内部的字符数组引用常量池里边的字符串内部的字符数组,意思是和u是同样的字符数组

使用图来表示的话,情况就大概是这样的(使用虚线只是表示两者其实没什么特别的关系):

 

测试demo:

        String m = "hello,world";String n = "hello,world";String u = new String(m);String v = new String("hello,world");System.out.println(m == n); //true System.out.println(m == u); //falseSystem.out.println(m == v); //falseSystem.out.println(u == v); //false

结论:

  • m和n是同一个对象

  • m,u,v都是不同的对象

  • m,u,v,n但都使用了同样的字符数组,并且用equal判断的话也会返回true

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

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

相关文章

java实现人脸识别V3版本开发

有段时间没有写更新公众号了,也许好多人都忘记了自己还关注了这么个公众号。因为这段时间确实是有其他的事比较忙,还有一个原因就是自己在技术方面没有学习新的东西,所以没有可更新的(包括博客)今天,我决定…

2018蓝桥杯省赛---java---A---7(三体攻击)

题目描述 题目:三体人将对地球发起攻击。为了抵御攻击,地球人派出了 A  B  C 艘战舰,在太空中排成一个 A 层 B 行 C 列的立方体。其中,第 i 层第 j 行第 k 列的战舰(记为战舰 (i, j, k))的生命值为 …

23种设计模式彩图

原文地址:http://www.jianshu.com/p/4a02646f7c9d.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

JDBC面试问题

转载自 JDBC面试问题 1.什么是JDBC API,何时使用它? Java DataBase Connectivity API允许我们使用关系数据库。JDBC API接口和类是 java.sql和javax.sql包的一部分。我们可以使用JDBC API来获取数据库连接,在数据库服务器中运行SQL查询和…

2018蓝桥杯省赛---java---A---9(倍数问题)

题目描述 代码实现 package lanqiao;import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner;public class Main {public static void main(String[] args){Scanner scanner new Scanner(System.in);int n scanner.ne…

HTML5知识点总结

 HTML5基础: 一、HTML: Hyper Text MarkUp Language(超文本标记语言)。 二、W3C: 1.world wide web consortium(万维网联盟),成立于1994年,WEB技术领域最权威和最具影响力的国际中立性技术标准机构。 2.w3c标准包括&…

漫画:什么是鸡尾酒排序

转载自 漫画:什么是鸡尾酒排序 那么,鸡尾酒排序又是何方神圣呢?我们这一期将会详细讲述。 让我们首先来回顾一下冒泡排序的思想: 冒泡排序的每一个元素都可以像小气泡一样,根据自身大小,一点一点向着数…

2018蓝桥杯省赛---java---A---10(付账问题)

题目描述 思路分析 用贪心算法,要使标准差最小,则需要将每个人需付的钱接近于平均值。如果有人的钱低于当前平均值a1,则需要将这人的钱全部支付,此人不够的钱需让其他人付,然后可以计算剩余人所需付钱的平均值a2&…

想要学习设计模式,你得先会看类图,一张图读懂UML

虚线箭头指向依赖; 实线箭头指向关联; 虚线三角指向接口; 实线三角指向父类; 空心菱形能分离而独立存在,是聚合; 实心菱形精密关联不可分,是组合;

数据库的这些性能优化,你做了吗

转载自 数据库的这些性能优化,你做了吗 在互联网项目中,当业务规模越来越大,数据也越来越多,随之而来的就是数据库压力会越来越大。 我们可能会采取各种方式去优化,比如之前文章提到的缓存方案,SQL优化…

青客宝团队Consul内部分享ppt

Consul 是一个支持多数据中心,分布式,高可用的服务发现和配置共享系统。由 HashiCorp 公司使用 Go 语言开发,基于Raft协议。部署起来非常容易,只需要极少的可执行程序和配置文件,具有绿色、轻量级的特点。 Consul是支持…

2018蓝桥杯省赛---java---C---9(小朋友崇拜圈)

题目描述 思路分析 数组来储存小朋友们的崇拜对象,然后下标1就是对应的小朋友座号,写一个方法找出每一个小朋友的崇拜圈大小,然后找出最大的崇拜圈即可 代码实现 package lanqiao;import java.util.*;public class Main {public static vo…

漫画:什么是时间复杂度

转载自 漫画:什么是时间复杂度 时间复杂度的意义 究竟什么是时间复杂度呢?让我们来想象一个场景: 某一天,小灰和大黄同时加入了一个公司...... 一天过后,小灰和大黄各自交付了代码,两端代码实现的功能…

Visual Studio 和 Team Foundation Server 产品维护及周期策略

1 适用于 Visual Studio 和 Team Foundation Server 2012 - 2017 这些产品遵循 Microsoft 10 年支持生命周期策略(5 年主流支持和 5 年扩展支持),起始日期为主要产品版本向全球 (RTW) 发布的日期。 例如,Visual Studio 2017 于 20…

28. 实现 strStr()---LeetCode---JAVA(今天又是一行超人)

class Solution {public int strStr(String haystack, String needle) {return haystack.indexOf(needle);} }

DevOps通用及版本控制面试题

转载自 DevOps通用及版本控制面试题 通用DevOps面试问题 此类别将包含与任何特定DevOps阶段无关的问题。这里的问题旨在测试您对DevOps的理解,而不是关注特定工具或阶段。 问题一: DevOps和Agile之间的根本区别是什么? 两者之间的差异…

微信和支付宝支付模式详解及实现(.Net标准库)

支付基本上是很多产品都必须的一个模块,大家最熟悉的应该就是微信和支付宝支付了,不过更多的可能还是停留在直接sdk的调用上,甚至和业务系统高度耦合,网上也存在各种解决方案,但大多形式各异,东拼西凑而成。…

.NET遇上Docker - 使用Docker Compose组织Ngnix和.NETCore运行

本文工具准备: Docker for WindowsVisual Studio 2015 与 Visual Studio Tools for Docker或 Visual Studio 2017 需要在安装时选择“容器开发支持”,如图: Docker的思想是将不同的应用放在不同的容器中分开运行,如运行.NetCore …

为什么大公司一定要使用DevOps

转载自 为什么大公司一定要使用DevOps 0 DevOps的意图 究竟什么是DevOps? 要想回答这个问题,首先要明确DevOps这个过程参与的人员是谁?即开发团队和IT运维团队!那么,DevOps的意图是什么呢?即在两个团队之间&#…

怎样访问Springboot项目中static中的资源

第一步 成功启动 第二步 输入 协议://ip:端口/资源的名字 eg http://localhost:8080/06-demo-point.html