欢迎光临我的博客[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);
System.out.println(s1 == s3);
System.out.println(s1 == s4);
System.out.println(s1 == s9);
System.out.println(s4 == s5);
System.out.println(s1 == s6);
特例一
public static final String A = "ab";
public static final String B = "cd";
String s = A + B;
String t = "abcd";
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种包装类默认创建了数值[-128,127]的相应类型的缓存数据,
但是超出此范围仍然会去创建新的对象
-128到127之 间的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;
int h = 127;
if (integerCacheHighPropValue != null) {
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
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关键字当然是每次都是新建一个,分配自己的空间
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· ASP.NET Core - 日志记录系统(二)
· .NET 依赖注入中的 Captive Dependency
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 终于决定:把自己家的能源管理系统开源了!
· C#实现 Winform 程序在系统托盘显示图标 & 开机自启动
· 了解 ASP.NET Core 中的中间件
· 实现windows下简单的自动化窗口管理
· 【C语言学习】——命令行编译运行 C 语言程序的完整流程