Java:String的“设计奥秘”

文章图片

花10分钟认真的看一篇文章或许有意想不到的收获
String类的内容非常多 , 一篇文章讲不完 , 当然如果一篇文章讲太多内容我相信你和我一样 , 就懒得看了 。 本文主要讲String类的“常量池” , 这是java在设计String类时一个很重要的设计 。
废话少说 , 先看定义!
01常量池的定义
String s1=\"test\";上面这个例子 , 很多小伙伴应该在很多的java面试题中见过 。
String s2=\"test\";
String s3=new String(\"test\");
System.out.println(s1==s2); //true
System.out.println(s1==s3); //false
造成上面这个原因就是因为有“字符串常量池”的存在 。 下面就来看一下什么是“字符串常量池”
当我们通过 String s1=\"test\"这种方式去赋值给String对象的时候 , jvm会去先查看下在String类型的常量池中是否有这样的一个字符串 , 如果有则把引用返回 , 没有则新创建一个一样内容的字符串并将其引用返回 , 但是在String类型的常量池中同一时间只会存在一个内容一样的字符串 , 所以这也就保证了唯一性 。看完上面这段话 , 小伙伴们应该就能明白为什么上面的s1=s2了 , 而s3这种方式其实在“字符串常量池”和“堆”上都创建了一个“test”但是s3的引用是指向“堆”的 , 而s1、s2的引用是指向“字符串常量池”中的“test”的 , 所以它们不想等 。
怕有些小伙伴不知道这里补充一句:Java中 , 只要使用new关键字来创建对象 , 则一定会堆区创建一个新的对象 , 堆中存放对象本身的数据 , 栈中存放对象的引用 , 例子中的s1、s2、s3都是引用都是存在栈中的 。
下面我们来看一下常量池在那
02常量池的位置介绍常量池的位置之前 , 需要简单的介绍一下 , “堆”、“栈”、“静态区”、“方法区”的概念 , 就简单了解一下 , 知道里面都放了些啥就行 , 不需要太深究 (ps:深究它干嘛 , 除非你想干程序员)
- 堆:用于存放对象内容的内存区域
- 方法区:也称非堆(Non-Heap) , 又是一个被线程共享的内存区域 。 其中主要存储加载的类字节码、class/method/field等元数据对象、static-final常量、static变量、jit编译器编译后的代码等数据
- 栈:每个线程包含一个栈区 , 栈中只保存基础数据类型的对象和自定义对象的引用(不是对象)
常量池是在方法区中的
下面再用一张图描述一下 , 上面例子中s1、s2、s3之间的关系
那么为什么java要这么去设计一个常量池呢?弄清这个原因或许才真的对我们有帮助
03为什么这么做?我们都知道
- 在java中String是一个类 , 类的使用都是需要去new的 , 在前面我们也见过通过new去创建字符串的方式 。
- java中只要new了就一定会去产生一个新的对象 。
这里java其实就做了特别处理 , 既然String类这么常用 , 那我就单独找一个空间来存放它 , 每次新建字符串的时候就到这个区域来看一下 , 如果有 , 就不新建了 。 这样一来就减少了内存开销 , 提高了性能 。
推荐阅读
- 程序员■Java程序员必知:HashMap进行put操作会不会引起死循
- 课工场郑州翔天信鸽|JavaScript最常用,java是主流,JetBrains公布编程语言排名
- 猿灯塔|POI Excel,Java架构-Apache
- 【Java】github上标星70.5k,贼火的Java突击手册,全面详细对标阿里P7
- 「编程」后台编程语言互相争执,为何前端公认JavaScript?
- 腾讯@JAVA如何连接数据库
- Java■Java仍然排名第一,但Kotlin不容小视了
- 「javascript」为什么NodeJS是创业公司的首选?了解用于Web开发的NodeJS
- 人世繁华|进行面向对象程序设计深剖,可以一学,大牛带你深入Java核心技术
- 环球科技在此|Java自动化测试框架(TestNG)——异常测试
