前言
知识网:
- 常量池
- 变量
- 常量
- 对象字面量
什么是常量池
常量池是JVM中线程共享的一块内存区域,Java会将 编译期就已经确定的数据 保存在常量池中,这样就避免了频繁的创建与销毁对象对系统性能的影响。
常量池中主要存放的就是 final常量 的值以及 对象字面量 的值。
常量池中是不会存在相等的数据的,因为在编译期间,每当常量需要赋值的时候,就回去常量池检测有没有该值,如果有则将该值的地址引向常量,如果没有该值,则在常量池中创建该值,再将值得内存地址引向常量。
知识撒网
Java代码执行过程: 我们知道,Java程序代码为实现跨平台会经历两个时期:一个是编译期、另一个是运行期。
为了方便理解,我们暂时将第二个时期再次拆分为解释期、运行期。如下:
第一个阶段我们称为编译期此时Java代码会通过javac编译成class文件。
第二个我们可以称为解释期此时classloader(类加载器)会将class文件中的成员变量,构造方法,成员方法等加载到内存中去。
第三个我们将之称为运行期此时就是我们熟悉的创建对象,开辟空间、分配内存、执行代码了。
变量:变量其实就是代表一个“可操作的存储空间”,空间位置是确定的,但是里面放置的是什么值是不确定的。我们可以通过变量名来访问“对应的存储空间”,从而操作这个“存储空间”存储的值。
常量:简单理解就是一切由final关键字修饰的变量都是final常量。常量需要在初始化的时候就赋值,而且一旦赋值就不能再更改。说白了就是由final声明一个固定值。
扫描二维码关注公众号,回复:
7667788 查看本文章
对象字面量:我们需要一个对象通常会new一个对象实例出来,而对象字面量则是直接把常量给对象赋值无需new出来的对象。例如:String对象以及部分基本类型的包装类对象。如下:
Integer a = 30 ; //在常量池中。 Integer b = new Integer(40); //在堆内存中开辟空间。 Integer c = 30; // 在常量池中,和a指向的地址一致。 String str1 = "你"; //在常量池中。 String str2 = "好"; //在常量池中。 String str3 = new String("吗"); //在堆内存中开辟空间。 String str4 = "你" + "好"; // "你好" 在常量池中。PS:两个确定的值,拼接还是固定值。 String str5 = str1 + str2 ;//在堆内存中。PS :str1、str2 运行期间指向的值可能变,所以是不固定的 str4 != str5 俩人不是一个世界的(内存地址不一样) String str6 = str5.intern(); // 在常量池中 intern()方法会在常量池中查找是否有值相等的字符串,有则返回引用,没有则在常量池添加该字符串。所以 str4 == str6 //PS:创建Str3的时候,实际上产生了一个或者两个对象 这和String的构造器有关 public String(String original) {...} //可以看出String的构造器是需要一个字符串作为参数的。此时new String(...)会在堆中创建一个对象,此时堆内存中开辟了相应的空间, //而需要的参数字符串会去常量池中查找有没有相同的值,有就直接引用(此时就产生一个对象),没有则会在堆内存开辟空间存入该值,并将该空间地址引向str3(此时则产生两个对象)。 //可以看出new String(...)过程开辟的空间没啥用,浪费了。 //我们知道,我们平时比较两个字符串的时候通常使用equals()方法,而equals()方法比较的是"值"是否相等,而没有比较"内存地址"是否相同。 // == 比较的则是 值是否相等 且 内存地址是否相同。