【Java_基础】java中的常量池
1.java常量池的介绍
java中的常量池,通常指的是运行时常量池,它是方法区的一部分,一个jvm实例只有一个运行常量池,各线程间共享该运行常量池。
java常量池简介:java常量池中保存了一份在编译期间就已确定的数据。它里面包括final常量的值(包括成员常量、局部常量和引用常量)、以及对象字面量的值。
在编译期间,每当给常量赋值它就会去检测常量池中是否存在该值,若存在直接返回该值的地址给常量,若不存在则先在常量池中创建该值,再返回该值的地址给常量。因此常量池中不可能出现相等的数据。
2.final常量
一切经final关键字修饰的变量均为常量,final常量必须在定义时就赋初值,否则编译不通过。
3.对象字面量
对象字面量是指直接以一常量给对象赋值,而不是在堆空间new出一个对象实例。
常见的两种对象字面量:基本类型的包装类对象字面量、String对象字面量。
3.1基本类型的包装类对象字面量
java中基本类型的包装类大都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean。这5种包装类默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。 两种浮点数类型的包装类Float,Double并没有实现常量池技术。
包装类型Integer与常量池
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0); System.out.println("i1=i2 " + (i1 == i2));
System.out.println("i1=i2+i3 " + (i1 == i2 + i3));
System.out.println("i1=i4 " + (i1 == i4));
System.out.println("i4=i5 " + (i4 == i5));
System.out.println("i4=i5+i6 " + (i4 == i5 + i6));
System.out.println("40=i5+i6 " + (40 == i5 + i6)); i1=i2 true
i1=i2+i3 true
i1=i4 false
i4=i5 false
i4=i5+i6 true
40=i5+i6 true
解释:
- Integer i1=40;直接以字面量给对象赋值,它会先去检查常量池中是否存在该值,若存在直接返回该值的地址,若不存在则现在常量池中创建该值,再返回该值的地址。
- Integer i1 = new Integer(40);这种情况会在堆空间创建新的对象。
- 语句i4 == i5 + i6,因为+这个操作符不适用于Integer对象,首先i5和i6进行自动拆箱操作,进行数值相加,即i4 == 40。然后Integer对象无法与数值进行直接比较,所以i4自动拆箱转为int值40,最终这条语句转为40 == 40进行数值比较。
3.2String对象字面量
String str1 = "abcd";
String str2 = new String("abcd");
System.out.println(str1==str2);//false String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";
String str4 = str1 + str2;
System.out.println("string" == "str" + "ing");// true
System.out.println(str3 == str4);//false String str5 = "string";
System.out.println(str3 == str5);//true
解释:
- 引用str1指向常量池中字符串"abcd"的地址,是在常量池中拿对象,new String("abcd")是直接在堆内存空间创建一个新的对象。只要使用new方法,便需要创建新的对象。
- 连接表达式 +,只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入常量池中。
- 对于字符串变量的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,其属于在运行时创建的字符串,具有独立的内存地址,所以不引用自同一String对象。
(3)String.intern()方法强制将字符串放入常量池中
public static void main(String[] args) {
String s1 = new String("计算机");
String s2 = s1.intern();
String s3 = "计算机";
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s3 == s2? " + (s3 == s2));
} s1 == s2? false
s3 == s2? true
解释:String的intern()方法会查找在常量池中是否存在一份equal相等的字符串,如果有则返回该字符串的引用,如果没有则添加自己的字符串进入常量池。
注意:final常量必须在定义时就赋初值,但对象字面量可以先定义后赋值。
4. 常量池的好处
常量池是为了避免频繁的创建和销毁对象而影响系统性能,实现了常量池中的内容由对象共享。例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
- 节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
- 节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等。
注:==号比较基本数据类型是值比较,但比较引用类型则是引用所指向的地址比较。
参考的博文:java常量池技术
【Java_基础】java中的常量池的更多相关文章
- Java中的常量池
JVM中有: Class文件常量池.运行时常量池.全局字符串常量池.基本类型包装类对象 常量池 Class文件常量池: class文件是一组以字节为单位的二进制数据流,在java代码的编译期间,编写的 ...
- java中Integer常量池
我们先看一个关于Integer的例子 public static void main(String[] args) { // TeODO Auto-generated method stu Integ ...
- Java中的常量池(字符串常量池、class常量池和运行时常量池)
转载. https://blog.csdn.net/zm13007310400/article/details/77534349 简介: 这几天在看Java虚拟机方面的知识时,看到了有几种不同常量池的 ...
- 19、java内存分配 常量池详解
在class文件中,“常量池”是最复杂也最值得关注的内容. Java是一种动态连接的语言,常量池的作用非常重要,常量池中除了包含代码中所定义的各种基本类型(如int.long等等)和对象型(如Stri ...
- 【万字图文-原创】 | 学会Java中的线程池,这一篇也许就够了!
碎碎念 关于JDK源码相关的文章这已经是第四篇了,原创不易,粉丝从几十人到昨天的666人,真的很感谢之前帮我转发文章的一些朋友们. 从16年开始写技术文章,到现在博客园已经发表了222篇文章,大多数都 ...
- Java基础-Java中的并法库之线程池技术
Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.
- java基础(八) 深入解析常量池与装拆箱机制
引言 本文将介绍常量池 与 装箱拆箱机制,之所以将两者合在一起介绍,是因为网上不少文章在谈到常量池时,将包装类的缓存机制,java常量池,不加区别地混在一起讨论,更有甚者完全将这两者视为一个整体, ...
- Java字面常量与常量池
Java中的字面常量(区别于final创建的有名常量)通常会保存在常量池中,常量池可以理解为像堆一样的内存区域.但是常量池有一个特性就是,如果常量池中已存在该常量将不会再次为该常量开辟内存 还是看个程 ...
- Java堆/栈/常量池以及String的详细详解(转)------经典易懂系统
一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...
随机推荐
- iOS 8 录音重放出现 OSStatus error 1685348671 / 2003334207 问题的解决办法
许多录音类 APP 都提供录音回放功能,大家在做这类 APP 的时候也经常会遇到这个需求.当大家用以前的套路在 iOS 8 上录音的时候,在模拟器上跑得挺好的,但是一上真机就跪了,为什么?因为真机底层 ...
- npm,cnpm,nrm区别
npm npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装.卸载.管理依赖等) nrm nrm只是单纯的提供了几个常用的下载包的uri地址,并能 ...
- STC单片机掉电断电失电瞬间EEPROM数据保存处理办法(转)
由于客户在请人设计开发一设备,但是设备用户处总停电,造成设备及其周边耗材损耗严重,因此请我司在现有STC为主要芯片的基础上做掉电瞬间EEPROM里的20个参数保存,上电后通过读取EEPROM中的参数回 ...
- vue文件的data中引入图片路径方式
data () { return { src:require('../assets/c.png') } }, mounted () { obj.src = require('../assets/'+ ...
- 前端开发 - Emmet使用手册
Emmet (前身为 Zen Coding) 是一个能大幅度提高前端开发效率的一个工具: 基本上,大多数的文本编辑器都会允许你存储和重用一些代码块,我们称之为"片段".虽然片段能很 ...
- PostgreSQL-2-用户权限管理
1.创建与删除用户 CREATE ROLE rolename; 方法1,创建角色 CREATE USER username; 方法2,创建用户 CREATE USER指令创建的用户默认是有登录权限的, ...
- 爬虫的UA池和代理池
爬虫的UA池和代理池 一.下载中间件 先祭出框架图: 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下 ...
- __enter__,__exit__上下文管理协议
上下文管理协议__enter__,__exit__ 用途或者说好处: 1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预 2.在需要管理一些资源比 ...
- springMVC-上传图片
SpringMVC文件上传与下载 上传图片 配置多媒体文件解析器 配置虚拟目录 在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加: <Context doc ...
- 转 shell模拟数据库的读写
0.create table create table myTestTable as select rownum as id, to_char(sysdate + rown ...