java常量池:字符串常量池,静态常量池,运行时常量池,

字符串常量池(String Poll)

  • java6:
    • 存在于永久代中。
    • 字符串常量池保存的是字符串常量。
  • java7:
    • 转移到了堆中。
    • 字符串常量池存的是字符串常量和堆内的字符串对象的引用。

静态常量池(class文件常量池)

  • 用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。
    • 字面量:文本字符串int long 等基本类型和被声明为final的常量值等。

    • 符号引用:是一组符号来描述所引用的目标,符号可以是任何形式的字面量一般包含以下三种:

      1. 类和接口的全限定名:例如对于String这个类,它的全限定名就是java/lang/String。
      2. 字段的名称和描述符:这里的字段就是类或者接口中声明的变量。
      3. 方法的名称和描述符:这里的描述符是方法的参数类型+返回值类型。
    • 静态常量池其实就是class文件里的一部分内容。以下图片是编译后的class文件。
      在这里插入图片描述

运行时常量池

  • 当类加载到内存中后,jvm就会将静态常量池中的内容存放到运行时常量池中。
  • 运行时常量池中的字符串在从静态常量池加载时
    1. 会先去String Poll中查询此此字符串在String Poll中的引用
    2. 如果没有则在String Poll中创建此字符串然后返回其引用
    3. 用返回的引用替换运行时常量池的字符串
  • 运行时常量池是全局共享的,多个类共用一个运行时常量池。并且class文件中常量池多个相同的字符串在运行时常量池只会存在一份

String.intern() 方法

  • jdk 6中:在String Poll中创建字符串常量。

  • jdk 7中: 如果字符串在堆中已经存在把堆得引用存入String Poll,不存在则在String Poll中创建字符串常量。

    • String str="";双引号会在String poll中直接创建。
    • String.valueOf(1);不会在String poll中直接创建。
    • (new Long(3l)).toString();不会在String poll中直接创建。
String s = new String("a");
System.out.println(s.intern() == s);// false
// 解析:此时创建了两个对象 1,"a"在字符串常量池中 2,s 在堆中new了新的字符串对象。
// 两个对象一个在String Poll中一个在堆中所以是false
String s = new String("a") + new String("b");// 1
System.out.println(s.intern() == s);//2
// true
        
// 解析:第1行代码创建了5个对象  字符串常量池中的:"a"和"b" 堆中的:new String("a")和new String("b")和s
// 第二行代码调用s.intern() 由于字符串常量池中并不存在"ab"所以会把s的引用放入String Poll 并返回这个引用 所以会返回true

猜你喜欢

转载自blog.csdn.net/qq_25825923/article/details/84972256