java中字符串常量池、class文件常量池、运行时常量池的区别

Java有三种常量池,即字符串常量池、class文件常量池、运行时常量池

java中字符串常量池、class文件常量池、运行时常量池的区别_第1张图片

  • Class常量池:保存类编译生成的字面量和符号引用。Class文件除了类字段,方法,接口描述等,还有Class常量池

  • 运行时常量池: 是JVM的概念,除了存放编译生成字面量和符号引用。还允许运行时产生常量,比如String.intern方法

    • JDK 1.6 中运行时常量池在方法区,而方法区放在内存中的永生代。
    • JDK 1.7中常量池从方法区中移了出来,在Java 堆(Heap)中开辟了一块区域存放运行常量池。
    • JDK1.8 将方法区直接放在一个与堆不相连的本地内存区域,这个区域被叫做元空间。
  • 字符串常量池。String类管理的常量池,处于堆内存中。

1. 字符串常量池——特殊的常量池,存在于方法区(method are), 不是堆

字符串常量池在每个VM中只有一份,他在内存中的位置如图,红色箭头所指向的区域 Interned Strings, 存在于方法区, 不是堆

java中字符串常量池、class文件常量池、运行时常量池的区别_第2张图片

抽象图


String str1 = “abc”; 

String str2 = “abc”; 

String str3 = “abc”; 

//new 一定会新建对象——且会有类似引用变量的指向常量池的"引用"行为

String str4 = new String(“abc”); 

String str5 = new String(“abc”);

面试题相信绝对是个经典兼考倒一堆人的题目

1. String a = new String("1"+"2")共建了几个对象?

2个

第一个:看构造器里面("1"+"2"),这个是在编译期就已经做了处理,即代表生成一个字符串:"12" 

第二个:当使用new的方法创建字符串时,注意这个”new“,就表示直接开辟了内存空间;然后把值"引用”的常量池中的“12”。最后返回该对象引用。

所以就创建了2个对象。

总结:

1. string的 "+操作符,先在常量池生成常量!!” 但是"+"操作符,有编译器优化

2. 有new String(...)的话: String也是常量池生成完之后!!才轮到堆;没有new,就不管堆的情况

2. 同理:String str="a"+"b"+"c" 共建了几个对象?

只有1个

在编译期已经常量折叠为"abc", 通过编译器优化后,得到的效果是

String str="abc" 

3. String str2 = new String("ABC") + "ABC" ; 会创建多少个对象?

3个

new String("ABC") :常量池+堆各一个,2个 

后面再 "+ ABC": 常量池新生成 “ABCABC" 1个

所以共3个


下面两个池都在方法区里(method area),是每个被加载的类,都有的

2. 运行时常量池(runtime constant pool)

当程序运行到某个类时,class文件中的信息就会被解析到内存的方法区里的运行时常量池中。看图可清晰感知到每一个类被加载进来都会产生一个运行时常量池,由此可知,每个类都有一个运行时常量池

3. class文件常量池(class constant pool)

class常量池也是在编译后每个class文件都有的

class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是 常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。

*字面量就是我们所说的常量概念,如文本字符串、被声明为final的常量值等。

*他在class文件中的位置如上图所示,Constant Pool 中。

你可能感兴趣的:(【java基础】,java)