常量池

欢迎光临我的博客[http://poetize.cn],前端使用Vue2,聊天室使用Vue3,后台使用Spring Boot

Java中的常量池#

Copy
Java常量池实际上分为两种形态:静态常量池和运行时常量池 常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。 静态常量池: 静态常量池是Class文件常量池(编译后的class文件的常量池),存放各个字面量值,符号引用的数据。 主要用于存放两大类常量:字面量(Literal)和符号引用量(Symbolic References)。 字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等。 运行时常量池(具备动态性): 是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存的方法区中。 我们常说的常量池,就是指方法区中的运行时常量池。

字符串示例#

Copy
String s1 = "Hello"; String s2 = "Hello"; String s3 = "Hel" + "lo"; String s4 = "Hel" + new String("lo"); String s5 = new String("Hello"); String s6 = s5.intern(); String s7 = "H"; String s8 = "ello"; String s9 = s7 + s8; System.out.println(s1 == s2); // true //所有参与拼接的部分都是已知的字面量,在编译期间,这种拼接会被优化,编译器直接帮你拼好 System.out.println(s1 == s3); // true //对于所有包含new方式新建对象(包括null)的“+”连接表达式,它所产生的新对象都不会被加入字符串池中 System.out.println(s1 == s4); // false //s7、s8作为两个变量,都是不可预料的,编译器毕竟是编译器,不可能当解释器用,不能在编译期被确定 //所以不做优化,只能等到运行时,在堆中创建s7、s8拼接成的新字符串,在堆中地址不确定,不可能与方法区常量池中的s1地址相同 System.out.println(s1 == s9); // false //二者都在堆中,但地址不同 System.out.println(s4 == s5); // false //s5在堆中,内容为Hello ,intern方法会尝试将Hello字符串添加到常量池中,并返回其在常量池中的地址 //因为常量池中已经有了Hello字符串,所以intern方法直接返回地址 System.out.println(s1 == s6); // true 特例一 public static final String A = "ab"; // 常量A public static final String B = "cd"; // 常量B String s = A + B; // 将两个常量用+连接对s进行初始化 String t = "abcd"; //s == t 成立 A和B都是常量,值是固定的,因此s的值也是固定的,它在类被编译时就已经确定了。 也就是说:String s=A+B; 等同于:String s="ab"+"cd"; 特例二 public static final String a; public static final String b; static { a = "123"; b = "456"; } public static void main(String[] args) { String c = "123456"; String d = a + b; System.out.println(c == d); } 编译期间,就已经确定了c,放在字符串常量池(堆中),但编译期static不执行的,a和b的值是未知的, static代码块,在初始化的时候被执行,初始化属于类加载的一部分,属于运行时常量池(方法区中)。 运行时是这样的String s6=new StringBuilder().append(s3).append(s4).toString();这里的过程是通过StringBuilder这个类实现的 它是通过new String()的方式来作为值进行返回的,所以是在堆中开辟的一块空间。所以和常量池中的不一样 1,在java 中,直接使用==操作符,比较的是两个字符串的引用地址,并不是比较内容,比较内容请用String.equals() 2,程序运行时,除非手动向常量池中添加常量(比如调用intern方法),否则jvm不会自动添加常量到常量池。

整型常量池、浮点型常量池等#

Copy
Byte,Short,Integer,Long,Character,Boolean都实现了常量池技术 数值类型的常量池不可以手动添加常量,程序启动时常量池中的常量就已经确定了, 比如整型常量池中的常量范围:-128~127, Byte,Short,Integer,Long,Character,Boolean这5种包装类默认创建了数值[-128127]的相应类型的缓存数据, 但是超出此范围仍然会去创建新的对象 -128127之 间的Integer会缓存到一个Integer数组中去了: 如果你要把一个int变成一个Integer对象,首先去缓存中找,找到的话直接返回引用给你,不必再新new一个, 如果不在-128-IntegerCache.high(127) 时会返回一个新new出来的Integer对象 Integer源码,里面有个静态类IntegerCache 它对Integer进行了缓存,范围是[-128,127],只要是这个范围内的数字都会缓存到这个里面,做成常量池进行管理 private static class IntegerCache { static final int high; static final Integer cache[]; static { final int low = -128; // high value may be configured by property int h = 127; if (integerCacheHighPropValue != null) { // Use Long.decode here to avoid invoking methods that // require Integer's autoboxing cache to be initialized int i = Long.decode(integerCacheHighPropValue).intValue(); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - -low); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for (int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() { } }

字符串常量池(String Constant Pool)#

Copy
存储编译期类中产生的字符串类型数据 JDK6.0及之前版本,字符串常量池是放在Perm Gen区(也就是方法区)中 JDK7.0版本,字符串常量池被移到了堆中了 运行时常量池和字符串常量池是独立的 String.intern() 检查字符串常量池中是否存在String并返回池里的字符串引用 若池中不存在,则将其加入池中,并返回其引用。 这样做主要是为了避免在堆中不断地创建新的字符串对象

class常量池(Class Constant Pool)#

Copy
每一个Java类被编译后,就会形成一份class文件 class文件中除了包含类的版本、字段、方法、接口等描述信息外 还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)

运行时常量池(Runtime Constant Pool)#

Copy
运行时常量池包含了类的运行时常量和静态方法等Class常量池的数据 JVM中运行时常量池在方法区中,是class常量池被加载到内存之后的版本 当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中 运行时常量池和字符串常量池是独立的

new关键字#

Copy
使用new关键字当然是每次都是新建一个,分配自己的空间
posted @   LittleDonkey  阅读(1250)  评论(0编辑  收藏  举报
编辑推荐:
· ASP.NET Core - 日志记录系统(二)
· .NET 依赖注入中的 Captive Dependency
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
阅读排行:
· 终于决定:把自己家的能源管理系统开源了!
· C#实现 Winform 程序在系统托盘显示图标 & 开机自启动
· 了解 ASP.NET Core 中的中间件
· 实现windows下简单的自动化窗口管理
· 【C语言学习】——命令行编译运行 C 语言程序的完整流程
点击右上角即可分享
微信分享提示
CONTENTS