java常量池(java 常量池)
各位老铁们好,相信很多人对java常量池都不是特别的了解,因此呢,今天就来为大家分享下关于java常量池以及java 常量池的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!
什么是JVM 运行时常量池
运行时常量池 vs常量池
要弄清楚方法区,需要理解清楚ClassFile,因为加载内的信息都在方法区。
要弄清楚方法区的运行时常量池,需要理解清楚ClassFile中的常量池。
一个Java源文件中的类、接口,编译后产生一个字节码文件。而Java中的字节码需要数据支持,通常这种数据会很大以至于不能直接存在字节码文件,换另一种方式,可以存在常量池,这个字节码包含了指向常量池的引用。在动态链接的时候会用到运行时常量池。
栈帧
[图片上传失败...(image-b8ec8b-1600702650468)]
动态链接
Javad方法区究竟存了什么???
java问题,请问在java中什么是直接量
直接量是指在程序中通过源代码直接给出的值,代码如下:
public static void main(String[] args)
{
//在这行代码中,为变量a所分配的初始值5就是一个直接量
int a= 5;
}
直接量的类型
并不是所有的数据类型都可以指定直接量,能指定直接量的通常只有三种类型,基本类型,字符串类型和null类型,具体而言,Java支持如下8种类型的直接量。
1),int类型的直接量:在程序中直接给出的整数数值
2),long类型的直接量:在整形数值后添加l或者L就变成了long类型的直接量
3),float类型的直接量:在一个浮点数后增加f或F就变成了float类型的直接量,这个浮点数可以是标准的小数形式,也可以是科学计数法形式
4),double类型的直接量:直接给出一个标准小数形式或者科学计数法形式的浮点数就是double类型的直接量
5),double类型的直接量:这个类型的直接量只有true和false
6),char类型的直接量:char类型的直接量有三种形式,分别是用单引号括起来的字符,转义字符和Unicode值表示的字符
7),String类型的直接量:一个用双引号括起来的字符序列就是String类型的直接量
8),null类型的直接量:这个类型的直接量只有一个值,即null
在上面的8种类型的直接量中,null类型是一种特殊类型,它只有一个值,null,而且这个直接量可以赋给任何引用类型的变量,用以表示这个引用类型变量中保存的地址为空,即
还未指向任何有效对象。
直接量的赋值
通常总是把一个直接量赋值给对应类型的变量,除此之外,还有两点需要注意:
1),Java还支持数值之间的自动类型转换,因此允许把一个数值直接量直接赋给另一种类型的变量,这种赋值必须是系统所支持的自动类型转换。
比如把int类型的直接量赋给一个long类型的变量。
2),String类型的直接量不能赋给其他类型的变量,null类型的直接量可以直接赋给任何引用类型的变量,包括String类型。
boolean类型的直接量只能赋给boolean类型的变量,不能赋给其他任何类型的变量。
关于字符串补充
先补充一个概念,什么是常量池?常量池(constant pool)值的是在编译期被确定,并被保存在已编译的.class文件中的一些数据,常量池包括了一些类,方法,接口中的常量
也包括字符串直接量。
当程序第一次使用某个字符串直接量时,Java会使用常量池来缓存该字符串直接量,如果程序后面的部分需要用到该字符串直接量时,Java会直接使用常量池中的字符串直接量。
String类是一个典型的不可变类,因此String对象创建出来就不可能被改变,所以无须担心共享String对象会导致混乱。
Java会确保每个字符串常量只有一个,不会产生多个副本。代码中使用一个字符串,他们在编译期就被确定下来了,在使用的时候,直接从该常量池中拿出来就好了。
public static void main(String[] args)
{
String name1="LinkinPark";
String name2="LinkinPark";
String name3="Linkin"+"Park";
//下面2行代码输出都为true
System.out.println(name1== name2);
System.out.println(name1== name3);
}
java 堆栈问题
献丑了:
1、java中所有变量(包括你上述提及的str引用类型变量)的存放位置都取决于该
变量的声明位置,而New出的对象则始终被JVM存放在堆中,创建的字串常
量则始终被JVM存放在数据段区常量池中。
2、你对第一个str引用变量存放位置的解释有一点欠妥的地方,准确的说这个
str的存放位置不一定在栈中,这要看str的声明位置,如果str是方法参数中
声明或方法内局部变量声明则存放位置就是你说的在栈中,但如果在类的成
员变量中声明则是存放于堆中。“abc”是一个字串常量被存放于常量池中而
该常量返回的引用地址被存放于str变量中,str变量的位置取决于str的声明
位置。
3、第二种方式String str= new String("abc");其实上是创建了两个对象,
与上述相同,字串常量对象被放在常量池中,这个常量“abc”与上面第一个
创建的“abc”是同一个abc,常量池中不能保存相同面值的常量,而New出的
新对象new String("abc")则存放在堆中,这里的“abc”的位置存在于堆
中,与上述常量池中的“abc”不是同一个“abc”,这里一定要注意啊,而
str变量的存放位置与第一个str的存放位置都是取决于该str的声明位置。
4、解释引用变量存放位置的原理:对象在创建时将为所有的成员变量分配内存
空间以及为所有的成员方法分配入口地址,因为对象是对属性及方法的封装
而对象在创建时被分配到堆中的空间,因此成员变量被分配在堆中,而方法
时在调用时为局部参数或变量临时分配内存空间,在此,方法在调用时被JVM
线程加载至栈中,于此局部变量及参数的所在位置存在与栈中,这些局部变
量及参数所占空间是临时的,一旦方法调用结束其临时空间将被释放,所以
内存栈区空间是为变量分配的临时存贮空间,这个你可以参考马士兵的堆栈
视屏教程,他讲述的很清楚,我可能还没有他表达得清楚。
5、最后再强调一点:变量不是都放在栈中,这取决于该变量的声明位置,我的
这种说法你能理解吗?只有理解了这一点,在出现堆栈问题或缓存遗留问题
时才能根据问题的出发点找到问题的出处。
OK,关于java常量池和java 常量池的内容到此结束了,希望对大家有所帮助。