java语言中常量池的概念分析

1.常量池的概念

  常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "hello"这种申明方式;当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。

  其主要可以分为四类

  1. class常量池
  2. 运行时常量池
  3. 基本字符类型包装类常量池
  4. 字符串常量池

1.class常量池:
在java中,每个java类被编译后就会生成一份class文件,class文件中除了包含的类的版本,字段之外,还有的信息就是常量池,用于存放斌一起生成的各种字面量和符号引用,存储相应的符号解析和符号引用。

2.运行时常量池

运行时常量池是在内存中的,是在class常量被加载到内存之后的版本,它的字面量可以动态的添加,符号引用可以解析为直接引用。JVM需要经过加载、链接、初始化等过程。下面我们通过代码来看下相应的结果

1 public class StringDemo{
2     public static void main(String hargs[]){
3          String logo = "a";
4          String strA = "hello.a.world";
5          //使用“+”进行字符串的连接,由于所用的内容都是常量,本质上表示一个字符串
6          String  strB = "hello." + logo + ".world";
7          System.out.println(strA == strB);//结果为false
8  }

 

本程序最大的特点在于利用了一个logo的对象定义了要连接的字符串内容,有logo属于程序运行时才可以确定的内容,这样就使得程序在编译时无法知道logo的内容,所以strB对象无法从字符串常量池中获得字符串的引用。

下面我们看下静态常量池的情况:

1 public class StringDemo{
2      public static void main(String hargs[]){
3          String strA = "hello.a.world";
4          //使用“+”进行字符串的连接,由于所用的内容都是常量,本质上表示一个字符串
5          String  strB = "hello." + "a" + ".world";
6          System.out.println(strA == strB);//结果为ture
7  }

在静态常量池中,所有参与连接的变量都是常量,所以在编译的时候会将这些常量组合在一起共同进行定义,这样就与strA对象的内容相同,最终的结果就是继续使用字符串常量中提供的内容为strB实例化,不会再开辟新的空间。

3.基本类型包装类常量池

ava 基本类型的包装类的大部分都实现了常量池技术。Byte,Short,Integer,Long这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character创建了数值在[0,127]范围的缓存数据,Boolean直接返回True或False,如果超出对应范围就会去创建新的对象。两种浮点数类型的包装类Float,Double并没有实现常量池技术。图片来源哈工大软件构造ppt。

 

 4.字符串常量池

JDK1.6及之前版本,字符串常量池存放在方法区中的,在JDK1.7版本以后,字符串常量池被移到了堆中了。

HotSpot VM里,记录interned string的一个全局表叫做StringTable,它本质上就是个HashSet<String>;这个StringTable在每个HotSpot VM的实例只有一份,被所有的类共享。

这里我们用一个图表例子来展示整个过程,图片来源java从入门到精通。

我们可以通过上面的形式看到字符串的引用修改过程,和其中相应的变化。

总结:

这篇博客到这里就结束了,希望能对你有所帮助,参考博客及书籍链接如下:

https://www.jb51.net/article/222551.htm

java从入门到精通

java核心技术

 

posted @ 2022-05-31 11:05  floral_sea  阅读(171)  评论(0)    收藏  举报