字符串equal_Java String:字符串常量池
作者:Seven_Nee
来自:https://segmentfault.com/a/1190000009888357
作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池:
字符串常量池的设计意图是什么?
字符串常量池在哪里?
如何操作字符串常量池?
字符串常量池的设计思想
字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能
JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化
为字符串开辟一个字符串常量池,类似于缓存区
创建字符串常量时,首先坚持字符串常量池是否存在该字符串
存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中
实现的基础
实现该优化的基础是因为字符串是不可变的,可以不用担心数据冲突进行共享
运行时实例创建的全局字符串常量池中有一个表,总是为池中每个唯一的字符串对象维护一个引用,这就意味着它们一直引用着字符串常量池中的对象,所以,在常量池中的这些字符串不会被垃圾收集器回收
代码:从字符串常量池中获取相应的字符串
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”) 创建多少个对象?
在常量池中查找是否有“abc”对象
有则返回对应的引用实例
没有则创建对应的实例对象
在堆中 new 一个 String("abc") 对象
将对象地址赋值给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");
会分配一个11长度的char数组,并在常量池分配一个由这个char数组组成的字符串,然后由m去引用这个字符串
用n去引用常量池里边的字符串,所以和n引用的是同一个对象
生成一个新的字符串,但内部的字符数组引用着m内部的字符数组
同样会生成一个新的字符串,但内部的字符数组引用常量池里边的字符串内部的字符数组,意思是和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
●编号1019,输入编号直达本文
●输入m获取文章目录
推荐↓↓↓
Python编程
字符串equal_Java String:字符串常量池相关推荐
- String和常量池
jdk1.6之前常量池属于永久代,jdk1.7以后移到堆中. String s1 = "abc";// 放在常量池中String s2 = "abc";// 从 ...
- JavaDay16-P104-P142—二分法查找—String类—常量池—包装—装箱、拆箱—NumberFormatException
1.二分法查找--建立在数组排序之上 案例程序: class BinarySearch{public static void binarySearch(int[] arr,int des) {Arra ...
- 百无聊赖之JavaEE从入门到放弃(十一)string类 常量池原理 内部类
目录 一.String类和常量池 1.String基础知识 2.常量池 二.内部类 1.概念 2.内部类的作用 3.注意 4.非静态内部类 5.静态内部类 6.匿名内部类 7.局部内部类 一.Stri ...
- java equals 字符串_Java String 字符串 比较 == equals
1.==该运算符表示指向字符串的引用是否相同,如t1==t2这种情况, 是因为在java中字符串的值是不可改变的,相同的字符串在内存中只会存一份, 所以t1和t2指向的是同一个对象,而t1==t4返回 ...
- 常量池之字符串常量池String.intern()
运行时常量池是方法区(PermGen)的一部分. 需要提前了解: 1. JVM内存模型. 2. JAVA对象在JVM中内存分配 常量池的好处 常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现 ...
- java string 常量池_用了这么久Java String,你真的懂字符串常量池吗?
字符串问题可谓是 Java 中经久不衰的问题,尤其是字符串常量池经常作为面试题出现.可即便是看似简单而又经常被提起的问题,还是有好多同学一知半解,看上去懂了,仔细分析起来却又发现不太明白. 本文以 J ...
- String:字符串常量池
一.设计思想 为字符串开辟一个字符串常量池,创建字符串常量时,首先检测字符串常量池是否存在该字符串.如存在该字符串对象,返回其引用:若不存在,实例化该字符串并放入常量池中,并返回其引用. 二.实现 ...
- JDK1.8+的String(字符串)常量池理解
在工作中使用String的地方很多,但是有时候会产生一点疑问,那就是项目中用到了这么多String,会不会对内存造成一定的压力,会不会降低程序的性能,字符串的值都存放到哪里去了?所以就深入了解了一下. ...
- JVM---StringTable(字符串常量池)
StringTable(字符串常量池) 字符串常量池 StringTable(字符串常量池) String的基本特性 String 的底层结构 String 的内存分配 String 的基本操作 字符 ...
最新文章
- XenStore: 使用,结构和原理
- tensorflow随笔-检测浮点数类型check_numerics
- 上海博彦科技 千万别来_这个年产值2870亿元的科技园区,将率多家企业亮相本届服贸会...
- get_children 方法里面参数 iv_as_copy 有什么用?
- [再学Python] - 6 - 函数的定义调用与返回
- 从零基础入门Tensorflow2.0 ----七、34 embedding rnn
- 从一个小Demo看React的diff算法
- Windows10 地平线4支持PS4手柄有线连接
- ACCESS中Dlookup函数使用
- matlab小苹果,我要用计算器弹曲子,求亲们发点计算器简谱
- BZOJ3168. 【HEOI2013】钙铁锌硒维生素
- 顺丰控股亏损:或时效件面临见顶危机,或下沉市场厮杀,或为220亿定增设局?
- Python零基础速成班-第1讲-认识Python,课程目标,安装环境以及完成第一行代码“hello world”
- 二级c语言编译完程序如何运行,计算机二级C语言辅导:C++环境下编译和运行c语言...
- html5定义一个变量,JavaScript 变量
- FIFO就是 first in first out 先进先出
- 良心推荐几款好玩的生存类手游:方舟生存进化、饥荒等等
- 政府网站绩效评估指标和要点
- 基于SSM的教务管理系统设计与实现
- 热点全能服务器系统,云服务器win系统开热点
热门文章
- DB2 错误代码 命令大全
- swiper链接href无效
- 计算机网络概述(一)
- android10全局黑暗,传Android 11或加入自动切换全局黑暗模式功能
- c#使用Path.Combine的一个坑
- php怎么实现简单的mvc框架,php实现简单的MVC框架实例
- spring版本 jdk8_从JDK8升级到JDK11,看这篇就足够了
- 服务器物品展示框刷物品,我的世界1period;11period;2展示框刷物品bug | 手游网游页游攻略大全...
- cmd中加载java源文件_如何在cmd中编译和运行java源文件
- RuntimeError: CUDA out of memory. Tried to allocate 132.00 MiB (GPU 2; 3.95 GiB total capacity; 3.41