返回顶部
首页 > 资讯 > 后端开发 > Python >Java常量池详解
  • 353
分享到

Java常量池详解

2024-04-02 19:04:59 353人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录(1)class常量池(2)运行时常量池 (3)基本类型包装类常量池(4)字符串常量池总结java中有几种不同的常量池,以下的内容是对java中几种常量池的介绍,其中最常见的就是

java中有几种不同的常量池,以下的内容是对java中几种常量池的介绍,其中最常见的就是字符串常量池。

(1)class常量池

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

其中字面量包括:1.文本字符串 2.八种基本类型的值 3.被声明为final的常量等;

符号引用包括:1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。

(2)运行时常量池

运行时常量池存在于内存中,也就是class常量池被加载到内存之后的版本,是方法区的一部分(jdk1.8 运行时常量池在元空间,元空间也是方法区的一种实现)。不同之处是:它的字面量可以动态的添加(String类的intern()),符号引用可以被解析为直接引用。

JVM在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,这里所说的常量包括:基本类型包装类(包装类不管理浮点型,整形只会管理-128到127)和字符串类型(即通过String.intern()方法可以强制将String放入常量池),运行时常量池是每个类私有的。在解析阶段,会把符号引用替换为直接引用。

(3)基本类型包装类常量池

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

Integer 缓存源码:



public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
      return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];
}

举个栗子:


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

解释:1-4语句结果应该很显然,因为Integer i1=40 这一行代码会发生装箱,也就是说这行代码等价于 Integer i1=Integer.valueOf(40),Integer.valueOf()方法基于减少对象创建次数和节省内存的考虑,缓存了[-128,127]之间的数字,如果在此数字范围内直接返回缓存中的对象。在此之外,直接new出来,显然40在常量池的缓存[-128,127]范围内;因此,i1 直接使用的是常量池中的对象。而Integer i1 = new Integer(40) 会直接创建新的对象;语句 i4 == i5 + i6,因为+这个操作符不适用于 Integer 对象,首先 i5 和 i6 进行自动拆箱操作,进行数值相加,即 i4 == 40。然后 Integer 对象无法与数值进行直接比较,所以 i4 自动拆箱转为 int 值 40,最终这条语句转为 40 == 40 进行数值比较,所以结果为true。第六条语句同理。

额外说明:所有整型包装类对象之间值的比较,全部使用 equals 方法比较。

对于Integer var = ?在-128至127之间的赋值,Integer对象是在 IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,推荐使用equals方法进行判断。

(4)字符串常量池

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

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

注意:它只存储对java.lang.String实例的引用,而不存储String对象的内容

字符串常量池和上面的基本类型包装类常量池有些不同,字符串常量池中没有事先缓存一些数据,而是如果要创建的字符串在常量池内存在就返回对象的引用,如果不存在就创建一个放在常量池中;

在Java中,有两种创建字符串对象的方法,一种是字面量直接创建,另一种是new一个String对象,这两种方法创建字符串对象的过程会不一样;


(1)String str = "abc";
(2)String str = new String("abc");

如果是第一种方式创建对象,因为是字面量直接创建,所以在编译的时候是确定的,如果该字符串不在常量池中会将该字符串放入常量池中并返回字符串对象的引用,如果在常量池中直接返回字符串对象的引用,如果是第二种方式创建对象,因为要创建String类型的对象,String对象是在运行时才加载到内存的堆中的,属于运行时创建,所以要先在堆中创建一个String对象,再去常量池中寻找是否有相同的字符串,如果有就返回堆中Sring对象的引用,如果没有则在将该字符串加入常量池中。

举个栗子:

比较下列两种创建字符串的方法:

String str1 = new String("abc");

String str2 = "abc";

答案:第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。 运行时期创建 。

第二种是先在栈中创建一个对String类的对象引用变量str2,然后通过符号引用去字符串常量池里找有没有”abc”,如果没有,则将”abc”存放进字符串常量池,并令str2指向”abc”,如果已经有”abc” 则直接令str2指向“abc”。“abc”存于常量池在 编译期间完成 。

String s = new String("abc")
这条语句创建了几个对象?

答案:共2个。第一个对象是”abc”字符串存储在常量池中,第二个对象在Java Heap中的 String 对象。这里不要混淆了s是放在栈里面的指向了Heap堆中的String对象。

String s1 = new String("s1") ;

String s1 = new String("s1") ;

上面一共创建了几个对象?

答案:3个 ,编译期常量池中创建1个,运行期堆中创建2个.(用new创建的每new一次就在堆上创建一个对象,用引号创建的如果在常量池中已有就直接指向,不用创建)

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: Java常量池详解

本文链接: https://lsjlt.com/news/135326.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java常量池详解
    目录(1)class常量池(2)运行时常量池 (3)基本类型包装类常量池(4)字符串常量池总结java中有几种不同的常量池,以下的内容是对java中几种常量池的介绍,其中最常见的就是...
    99+
    2024-04-02
  • java常量池图文详解
    java常量池是一个经久不衰的话题,也是面试官的最爱,题目花样百出,小菜早就对常量池有所耳闻,这次好好总结一下。推荐:java视频教程jvm虚拟内存分布:程序计数器是jvm执行程序的流水线,存放一些跳转指令,这个太高深,小菜不懂。本地方法栈...
    99+
    2016-07-05
    java
  • Java 常量池的实例详解
    Java 常量池的实例详解Java的常量池中包含了类、接口、方法、字符串等一系列常量值。常量池在编译期间就已经确定,并保存在*.class文件中一、对于相同的常量值,常量池中只保存一份拷贝。而且,当一个字符串由多个字符串常量链接而成时,多个...
    99+
    2023-05-31
    java 常量池 ava
  • Java字符串常量池示例详解
    为什么会有常量池的概念? 不知道小伙伴们是否有思考过这个问题? 没有思考也无所谓,小编在这里类比一下,大家就会清晰了。什么是池? 我们听的最多的池,应该是数据...
    99+
    2024-04-02
  • 详解JVM之运行时常量池
    目录class文件中的常量池运行时常量池静态常量详解符号引用详解String Pool字符串常量池总结class文件中的常量池 之前我们在讲class文件的结构时,提到了每个clas...
    99+
    2024-04-02
  • Java 线程池常见问题详解
    线程池是一个预定义线程集合,可按需提供给应用程序使用。它通过管理线程的创建和销毁,简化了线程处理,提高了应用程序的性能和可伸缩性。 为什么使用线程池? 使用线程池有以下好处: 减少线程创建和销毁的开销,提高性能。 限制并发线程数,防止系...
    99+
    2024-03-13
    线程池
  • 深入探索Java常量池
    Java的常量池通常分为两种:静态常量池和运行时常量池静态常量池:class文件中的常量池,class文件中的常量池包括了字符串(数字)字面值,类和方法的信息,占用了class文件的大部分空间。运行时常量池:JVM在完成加载类之后将clas...
    99+
    2023-05-30
    java 常量池 ava
  • java学习之JVM运行时常量池理解
    运行时常量池 运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息时常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将...
    99+
    2024-04-02
  • 如何解析Java常量池与字符串intern
    这期内容当中小编将会给大家带来有关如何解析Java常量池与字符串intern,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。在Java应用程序运行时,Java虚拟机会保存一份内部的运行时常量池,它区别于cl...
    99+
    2023-06-17
  • Java中的堆、栈和常量池怎么理解
    这篇文章主要讲解了“Java中的堆、栈和常量池怎么理解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中的堆、栈和常量池怎么理解”吧!1.寄存器最快的存储区, 由编译器根据需求进行分配...
    99+
    2023-06-17
  • java线程池详解
    线程池概述 线程池就是一个管理线程的池子,可以降低创建和销毁线程带来的资源消耗因为线程其实也是一个对象,创建一个对象,需要经过类加载过程,销毁一个对象,需要走GC垃圾回收流程,都是需要资源开销的。 提高响应速度,任务到达了相对于从线程池取线...
    99+
    2015-04-06
    java基础 线程池 java
  • JVM常量池的深入讲解
    提示:这里咱们要说的常量池,常量池就是咱们面试中所说的常量池,谈谈你对常量池的认识?面试官一问咱们就懵逼了,你要记得你脑子中有一张图!!! 剩下的就好办了 提示:请各位大佬批评指正!...
    99+
    2024-04-02
  • Java线程池 ThreadPoolExecutor 详解
    目录一 为什么要使用线程池二 线程池原理详解2.1 线程池核心组成2.2 Execute 原理三 线程池的使用3.1 创建线程池3.1.1 自定义线程池3.1.2 功能线程池3.1....
    99+
    2024-04-02
  • Java String类的理解及字符串常量池介绍
    目录一. String类简介1. 介绍2. 字符串构造二. 字符串常量池(StringTable)1. 思考?2. 介绍和分析3. intern方法三. 面试题:String类中两种...
    99+
    2024-04-02
  • Java常量池面试题的示例分析
    这篇文章主要介绍Java常量池面试题的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!今天My partner问我一个让他头疼的Java question,求输出结果: public cla...
    99+
    2023-06-17
  • 如何理解Java 虚拟机中的String 类和常量池
    本篇文章为大家展示了如何理解Java 虚拟机中的String 类和常量池,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、String 对象的两种创建方式String str1 ...
    99+
    2023-06-05
  • 详解Java 虚拟机(第④篇)——8 种基本类型的包装类和常量池
    Java 基本类型的包装类的大部分都实现了常量池技术, 即Byte,Short,Integer,Long,Character,Boolean; 这 5 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据, 但是超出此范围仍然...
    99+
    2023-06-05
  • Java线程池详细解读
    目录1、线程池1.1 线程池概念1.2 线程池的实现2、StringBuffer类面试题:请解释String、StringBuffer、StringBuilder的区别?3、...
    99+
    2024-04-02
  • javascript有没有常量池
    这篇文章主要介绍“javascript有没有常量池”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“javascript有没有常量池”文章能帮助大家解决问题。 ...
    99+
    2024-04-02
  • JAVA中字符串常量池和缓冲池的作用是什么
    这篇“JAVA中字符串常量池和缓冲池的作用是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JAVA中字符串常量池和缓冲池...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作