字面量
int a = 1; //这个1就是字面量。
String a = "abc"; //a被称为(变量名、标识符、对象的引用),这个abc就是字面量。
符号引用
一个java类将会编译成一个class文件。在编译时,java类并不知道引用类的实际内存地址,因此只能使用符号引用来代替。
比如org.simple.People类要引用org.simple.Tool类,在编译时People类并不知道Tool类的实际内存地址,因此只能使用符号org.simple.Tool(假设)来表示Tool类的地址。而在类装载器装载People类时,此时可以通过虚拟机获取Tool类 的实际内存地址,因此便可以既将符号org.simple.Tool替换为Tool类的实际内存地址,及直接引用地址
直接引用地址
//符号引用
String str ="abc";
System.out.print("str="str);
//直接引用
System.out.print("str="abc);
在类加载过程中的验证步骤下的:准备—>解析—>初始化,符号引用转换为直接引用就发生在解析阶段
符号引用和直接引用有什么联系与区别
符号引用:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。
直接引用:直接引用可以使直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用是与虚拟机实现的内存布局相关的,同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用,那引用的目标必定已经在内存中存在。
常量
常量一词有两种理解,两者概念不可等同!!
一个理解:用字面量表示的,为区分不同的数据类型的值(若更改了,将是另一个常量了)
常量类型 | value |
---|---|
整型常量(java默认int) | 123 |
实型常量 (java默认double) | 3.14 |
字符串常量 | “HelloWorld” |
逻辑常量 | true/false |
一个理解为常量就是定义在代码中的在程序运行时一直存在且不能改变的变量!
用final关键字修饰的变量(常量:一般规范常量名字母都大写)、还可以用于类(final类不可继承)、函数(final函数不可被重写)等
final String STR = new String("abc");
为什么会经常将final和static关键字一起使用?
静态变量:带有static关键字的方法或变量为该class的公有方法和变量。其生命周期随着class创建或销毁,并保存在方法区内存中,静态方法(方法区中)只能引用静态变量,在静态方法内不可以使用this或者super等关键字。
static final用来修饰成员变量和成员方法,可简单理解为“全局常量”!
对于变量,表示一旦给值就不可修改(final特性),并且通过类名可以访问(static特性)。
对于方法,表示不可覆盖,并且可以通过类名直接访问。
常量池
String a = "abc";
String b = new String("abc");
对象b的实例储存在堆中!!
而a的值作为字面量一开始储存在了class文件中,之后运行期,转存至方法区中。
静态常量池:是编译后.class文件的常量池,可以理解为class文件的资源仓库,主要存放两大类常量:字面量和符号引用。
运行时常量池:就是在class文件被加载进了内存之后,常量池保存在了方法区中,通常说的常量池 指的是运行时常量池。运行时常量池相对于class常量池(静态常量池)有一个重要特征就是具有动态性。运行时常量池随着方法区(逻辑概念)的具体实现不同存在的位置也不同,1.8之前在堆,1.8之后在本地内存(Native memory){也称为C-Heap,是供JVM自身进程使用的!}
常量池的好处
常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。
例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
java的数据在内存中分配
- java数据共有8种基础数据类型和一个String引用类型,String类和6种数据类型的包装类都实现常量池技术(除了Boolean外,其他都只对小于128的值才支持,常量池仅仅是【-128至127】这个范围内的常量,如果常量值超过这个范围,就会从堆中创建对象,不再从常量池中取)
- 两种浮点数类型的包装类Float,Double并没有实现常量池技术
Double aDouble = 1.0;相当于 Double aDouble = new Double(1.0);
Float aFloat= (float) 1.0;相当于 Float aFloat = new Float(1.0);
- String类型也实现了常量池技术,但是稍微有点不同。String型是先检测常量池中有没有对应字符串,如果有,则取出来;如果没有,则把当前的添加进去。
定义 | 内存 |
---|---|
局部变量(基础类型) | 栈 |
局部变量(引用类型) | 堆 |
成员变量(基础类型) | 堆 |
成员变量(引用类型) | 堆 |
final常量(String类型) | 常量池 |
final常量(引用类型) | 堆 |
final常量(基础类型) | 栈 |
包装类和String(符合条件的) | 常量池 |
基础类型的字面量和" " | 运行前在静态常量池 |