Java常量池

article/2025/9/24 0:16:21

Java常量池

  一.相关知识

  1.何为常量

  第一种常量:是一个值,我们将这个值本身称为常量。比如:

整型常量:1024
实型常量:1.024
字符常量:'g' 'c' 'w'
字符串常量:"gcw"
逻辑常量:true false

   例如,我们可以将数字1024称为一个int类型的常量。
  第二种常量:不可变的变量,我们也称为常量。被关键字final修饰的变量,其值就不可以改变。可能它本身是个变量,但是被final修饰后,我们就可以认为它是个常量。比如:

final int i=1024;

   2.常量池

  常量池分为两种:静态常量池和运行时常量池。
  (1)静态常量池也就是Class字节码文件中的常量池。我们举一个简单的例子,下面是一个HelloWorld的源文件和Class文件。
  源文件:

public class HelloWorld{public static void main(String args[]){System.out.println("hello world");}
}

   class文件:

  我们对class文件中的标识符予以一一分析。

  ①魔数
  魔数是class字节码文件中的前四个字节:ca fe ba be(漱壕)。它的唯一作用是确定这个文件是否可以被JVM接受。很多文件存储标准中都使用魔数来进行身份识别。
  ②版本号
  第5和第6个字节是次版本号,第7个和第8 个是主版本号。这里的第7和第8位是0034,即:0x0034。0x0034转为10进制是52。Java的版本是从45开始的然而从1.0 到1.1 是45.0到45.3, 之后就是1.2 对应46, 1.3 对应47 … 1.6 对应50,这里的1.6.0_24对应的是52,就是0x0034;
  ③常量池的入口
  由于常量池中的常量的数量不是固定的,所以常量池的入口需要放置一项u2类型的数据,代表常量池的容量计数值。这里的常量池容量计数值是从1开始的。如图常量池的容量:0x001d(29)。所以共有29个常量。
  ④常量池
  常量池中主要存放两类常量:字面量和符号引用。字面量是比较接近Java语言层面的常量概念,也就是我们提到的常量。符号引用则属于编译原理的方面的概念,包括三类常量:类和接口的全限定名;字段的名称和描述符;方法的名称和描述符。

  (2)运行时常量池:运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外还有一项信息是常量池,它用于存放编译期生成的字面量和符号应用,这部分内容将在类加载后进入方法区的时候存到运行时常量池中。运行时常量池还有个更重要的的特征:动态性。Java要求,编译期的常量池的内容可以进入运行时常量池,运行时产生的常量也可以放入池中。常用的是String类的intern()方法【当调用 intern() 方法时,编译器会将字符串添加到常量池中(stringTable维护),并返回指向该常量的引用。 】。

  3.常量池的好处
  常量池是为了避免频繁地创建和销毁对象而影响系统性能,其实现了对象的共享。
  例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
  (1)节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
  (2)节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等。

  4.equals和==的区别
   Java中的数据类型分两种:基本数据类型和引用数据类型。
  (1)基本数据类型共8种:byte short int long char float double boolean。
  对于基本数据类型的比较,都是用==来比较两者的值是不是相等。
  (2)引用数据类型。
  一般情况下,equals和==是一样的,都是比较的两者的地址值是不是一样。但是也有特殊情况,比如,我们都知道所有类都是继承自Object基类,Object中的equals方法中是使用==来实现的,即比较的是两者的地址值。但是,Object的子类可以重写equals方法,比如Date、String、Integer等类都是重写了equals()方法,比较的是值是否相等。例如,在String类的equals()源码中,先比较是不是指向同一个地址,如果不是再比较两者是不是值相等。这个时候,equals和==所表达的含义显然就不一样了。  

public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String) anObject;int n = count;if (n == anotherString.count) {char v1[] = value;char v2[] = anotherString.value;int i = offset;int j = anotherString.offset;while (n-- != 0) {if (v1[i++] != v2[j++])return false;}return true;}}return false;}

   二.8种基本数据类型

  8种基本数据类型都有自己的包装类,其中有6个包装类(Byte,Short,Integer,Long,Character,Boolean)实现了常量池技术。举例来说,通过查看Integer的源码会发现,它有个内部静态类IntegerCache,这个内部静态类进行了缓存,范围是[-128,127],只要是这个范围内的数字都会缓存到里面,从而做成常量池进行管理。我们来看一个实例:

package com.itszt.test5;
/*** Integer常量池*/
public class IntegerTest {public static void main(String[] args) {Integer i1=10;Integer i2=10;//在[-128-127之间,存入常量池]System.out.println("i1 ==i2 ---> " + (i1==i2));Integer i3=1000;Integer i4=1000;//超出常量池范围,各自创建新的对象System.out.println("i3 ==i4 ---> " + (i3==i4));}
}

   控制台打印结果:

i1 ==i2 ---> true
i3 ==i4 ---> false

   上述代码中,第一次把i1的值缓存进去了,当创建i2的时候,它其实是指向了第一次缓存进去的那个10,所以i1和i2指向了同一个地址;由于i3和i4均超出了常量池范围,故在堆内存中重新创建了两个对象,它们在堆内存中的地址不相等。

  如果使用new关键字,意味着在堆内存中开辟了新的一块内存孔家。每次new一个对象都是在堆内存中开辟一块新的空间,所以每一个new出的对象的地址都不一样。

  Float和Double没有实现常量池。代码演示如下:

        Float f1=10.0f;Float f2=10.0f;System.out.println("f1 =f2 ---> " + (f1==f2));Double d1=12.0;//默认为double类型Double d2=12.0d;System.out.println("d1 =d2 ---> " + (d1==d2));    

   上述代码在main()主函数中执行后,控制台打印如下:

f1 = f2 ---> false
d1 =d2 ---> false

   三.String类

  1.new String都是在堆上创建字符串对象。

   

  2.当调用 intern() 方法时,编译器会将字符串添加到常量池中(stringTable维护),并返回指向该常量的引用。

  

  3.通过字面量赋值创建字符串(如:String str=”twm”)时,会先在常量池中查找是否存在相同的字符串,若存在,则将栈中的引用直接指向该字符串;若不存在,则在常量池中生成一个字符串,再将栈中的引用指向该字符串。

  4.常量字符串的“+”操作,编译阶段直接会合成为一个字符串。如string str=”JA”+”VA”,在编译阶段会直接合并成语句String str=”JAVA”,于是会去常量池中查找是否存在”JAVA”,从而进行创建或引用。

  5.对于final字段,编译期直接进行了常量替换(而对于非final字段则是在运行期进行赋值处理的)。
  final String str1=”ja”;
  final String str2=”va”;
  String str3=str1+str2;
  在编译时,直接替换成了String str3=”ja”+”va”,然后再次替换成String str3=”JAVA”。

  6.常量字符串和变量拼接时(如:String str3=baseStr + “01”;)会调用stringBuilder.append()在堆内存上创建新的对象。

  7.在JDK 1.7后,intern()方法还是会先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用,这一点与之前没有区别,区别在于,如果在常量池中找不到对应的字符串,则不会再将字符串拷贝到常量池,而只是在常量池中生成一个对原字符串的引用。简单的说,就是往常量池放的东西变了:原来在常量池中找不到时,复制一个副本放到常量池,1.7后则是将在堆上的地址引用复制到常量池。

  

  四.常见试题解答:

Q:下列程序的输出结果:
String s1= “abc”;
String s2= “abc”;
System.out.println(s1==s2);
A:true,均指向常量池中对象。Q:下列程序的输出结果:
String s1=new String(“abc”);
String s2=new String(“abc”);
System.out.println(s1==s2);
A:false,两个引用指向堆中的不同对象。Q:下列程序的输出结果:
String s1 = “abc”;
String s2 = “a”;
String s3 = “bc”;
String s4 = s2 + s3;
System.out.println(s1 == s4);
A:false,因为s2+s3实际上是使用StringBuilder.append来完成,会生成不同的对象。Q:下列程序的输出结果:
String s1 = “abc”;
final String s2 = “a”;
final String s3 = “bc”;
String s4 = s2 + s3;
System.out.println(s1 == s4);
A:true,因为final变量在编译后会直接替换成对应的值,所以实际上等于s4=”a”+”bc”,而这种情况下,编译器会直接合并为s4=”abc”,所以最终s1==s4。Q:下列程序的输出结果:
String s = new String(“abc”);
String s1 = “abc”;
String s2 = new String(“abc”);
System.out.println(s == s1.intern());
System.out.println(s == s2.intern());
System.out.println(s1 == s2.intern());
A:false,false,true。 
posted @ 2018-04-22 20:39 奔跑在梦想的道路上 阅读( ...) 评论( ...) 编辑 收藏

http://chatgpt.dhexx.cn/article/f9jommuR.shtml

相关文章

Java 常量池

常量池分为 Class 常量池常量池、运行时常量池、字符串常量池。 1、 Class 常量池常量池(静态常量池) Java 文件被编译成 Class 文件,Class 文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项就是 Class 常量池&am…

JAVA常量池,一篇文章就足够入门了。(含图解)

前言 一直在《深入理解JVM》对常量池只有一个浅薄的了解,之前也遇到过这种题目,今天还是要挑出来进行一次全方位的了解。 常量池分类 常量池大体可以分为:静态常量池,运行时常量池。 静态常量池 存在于class文件中&#xff0c…

基于Elman神经网络的刀具剩余使用寿命预测(初学者+matlab代码实现)

1.Elman介绍 Elman神经网络是 J. L. Elman于1990年首先针对语音处理问题而提出来的,是一种典型的局部回归网络( global feed forward local recurrent)。Elman网络可以看作是一个具有局部记忆单元和局部反馈连接的递归神经网络 它的主要结构是前馈连接, 包括输入层、…

通过模拟退火改进的Elman神经网络(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 神经网络是一个庞大的体系和概念,根据处理信息的不同方式来区分不同的network。比如根据处理信息结果的传递方向&am…

基于遗传算法优化的Elman神经网络数据预测-附代码

基于遗传算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于遗传算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于遗传优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要:针…

【预测模型-ELAMN预测】基于海鸥算法优化ELMAN神经网络实现数据回归预测

1 简介 风能,作为一种重要,有潜力,无污染,可再生、可持续的能源,已经成为全球发电最为迅速的能源之一,越来越受到世界各国的青睐。近年来,为缓解能源短缺问题,改善环境,实现经济乃至人类的可持续发展,世界各国纷纷大力发展风能资源。然而,在实际操作中,风能固有的波动性和间歇…

MATLAB神经网络应用之Elman神经网络

Elman神经网络通常由输入层、隐含层和输出层构成,它存在从隐含层的输出到隐含层输入的反馈。这种反馈连接的结构使得被训练后不仅能识别和产生空域模式,还能够识别和产生时域模式,在此只介绍创建Elman网络的newelm函数,该函数用于…

基于粒子群算法优化的Elman神经网络数据预测-附代码

基于粒子群算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于粒子群算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于粒子群优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&#x…

elman神经网络的实现

在看文章时,一篇文章提到了使用elman神经网络来对癫痫病人的脑电信号与正常人的脑电信号进行区分,并且取得了较好的分类结果。于是就想自己写一个elman神经网络demo看看效果。 elman神经网络和感知机的差别通过下面的图片可以很明显的看出哪里不一样&am…

【预测模型-ELAMN预测】基于遗传算法优化ELMAN神经网络实现数据回归预测matlab代码

1 简介 风能,作为一种重要,有潜力,无污染,可再生、可持续的能源,已经成为全球发电最为迅速的能源之一,越来越受到世界各国的青睐。近年来,为缓解能源短缺问题,改善环境,实现经济乃至人类的可持续发展,世界各国纷纷大力发展风能资源。然而,在实际操作中,风能固有的波动性和间歇…

【预测模型】基于Elman神经网络预测电力负荷matlab代码

​1 简介 为提高甘肃电网负荷预测精度,提出了一种基于神经网络的负荷预测方法.针对甘肃电力系统负荷数据的非线性和动态特性,在多层前向BP网络中引入特殊关联层,形成有"记忆"能力的Elman神经网络,从而可以映射系统的非线性和动态特性.在网络训练算法中,采用自适应学…

粒子群算法优化BP和Elman神经网络-matlab源码

粒子群优化算法是一种智能优化算法,又称微粒群算法,它通过模拟自然界鸟群捕食和鱼群捕食的过程。通过群体中的协作寻找到问题的全局最优解。 收敛性的数学证明帮助了PSO的发展和应用,但此内分析具有很大的局限性。为PSO加入正交学习后&#…

基于鲸鱼算法优化的Elman神经网络数据预测-附代码

基于鲸鱼算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于鲸鱼算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于鲸鱼优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要:针…

基于小波Elman神经网络的短期风电功率预测

风力发电在全球范围内快速发展,装机容量逐年增加,截止2013 年底,中国风电新增装机容量约 16.1GW,较 2012 年的 12.96GW 大幅提高了 24%,中国风电累计装机已超过 90GW。 风力发电并网运行是实现大规模风能发利用的有效途径。但是与常规能源不…

基于灰狼算法优化的Elman神经网络数据预测

基于灰狼算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于灰狼算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于灰狼优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要:针…

Elman神经网络

newelm()函数: clear ; close all; clc %原始数据 data[0.4413,0.4707,0.6953,0.8133;...0.4379,0.4677,0.6981,0.8002;...0.4517,0.4725,0.7006,0.8201;...0.4557,0.4790,0.7019,0.8211;...0.4601,0.4811,0.7101,0.8298;...0.4612,0.4845,0.7188,0.8312;...0.4615,…

Elman神经网络与自适应共振网络(ART)

这几天在回过头看一些比较基础的东西,发现了两个早期研究的神经网络,Elman与ART网络,类似于上世纪80年代的hopfield神经网络,BM/RBM/DBN,RBF,SOM,以及同时期的SVM算法等等,虽然那个时…

Elman神经网络原理

Elman神经网络 近期开题,阅读到了一篇文章关于故障诊断的,其中用到了Elman神经网络,具体是结合EMD、PCA-SOM的Elman的性能评估/预测故障诊断,对Elman神经网络有点陌生,网上资源也讲的特别杂,来做个汇总Int…

【神经网络第一期】Elman神经网络基本原理

1. Elman神经网络概述 根据神经网络运行过程中的信息流向,可将神经网络可分为前馈式和反馈式两种基本类型。前馈式网络通过引人隐藏层以及非线性转移函数可以实现复杂的非线性映射功能。但前馈式网络的输出仅由当前输入和权矩阵决定,而与网络先前的输出…

回归预测 基于ELMAN递归神经网络预测及其matlab代码实现

文章目录 1. ELMAN神经网络的简介和算法描述1.1 Elman网络介绍1.2 Elman结构组成 1.3 ELMAN训练界面的参数解读2. 建立ELMAN神经网络的步骤3. 编写MATLAB代码4. ELMAN程序运行结果4.1 各层的神经元个数的确定过程4.2 预测值和真实值的误差计算(SSE、MAE、MSE、RMSE、…