zoukankan      html  css  js  c++  java
  • JDK8常量池整理

    1、常量

    字面量包括:1.文本字符串 2.八种基本类型的值 3.被声明为final的常量等;

    符号引用包括:1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。

    2、常量池分类

    类文件常量池:又称为静态常量池,存储区域在堆中,编译时产生对应的class文件,主要包含字面量和符号引用;

    运行时常量池:存在元数据(Meta Space)空间,JVM运行时,在类加载完成后,将每个class常量池中的符号引用转换为直接引用

    字符串常量池:存在堆内存中,类在加载、验证、准备完成后在堆中生成字符串对象实例,然后将该字符串对象实例的引用只存储到Sting Pool中,String Pool是一个StringTable类,是哈希表结果,里面存储的是字符串引用,具体的实例对象存储在堆中,这个stringtable表在每个hotspot中的实例只有一份,被所有类共享。

    基本类型包装类常量池:

    3、运行时常量池

    运行时常量池是方法区元数据区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述信息外,还有常量池表(用于存放编译期生成的各种字面量和符号引用)。

    1、JDK1.7之前版本运行时常量池包含字符串常量池位于方法区。
    2、JDK1.7版本字符串常量池位置从方法区搬到了堆中; 运行时常量池还在方法区。
    3、JDK1.8hotspot永久代被元空间(Metaspace)取代, 字符串常量池位置还在堆中, 运行时常量池位置变成了元空间(Metaspace)。

    4、字符串常量池

     1 package com.javabasic.str;
     2 
     3 public class StringTest1 {
     4 
     5     public static void main(String[] args) {
     6         //对象创建两种方式
     7         //第一种:创建了几个对象呢? 1个或2个 第一个对象:如果常量池中已有"abc"直接返回引用,如果不存在就创建一个;第二个对象:在堆内存中new的String对象。
     8         String s1 = new String("abc");//s1指向堆内存对象的引用地址
     9         
    10         //第二种:堆内存字符常量池(首先检查字符串常量池中是否存在,如果存在则直接引用,不存在添加进入)
    11         String s2 = "abc";//指向字符串常量池引用
    12         String s3 = "abc";//指向字符串常量池引用
    13         System.out.println(s1==s2);//false
    14         System.out.println(s2==s3);//true
    15         System.out.println("1>>>>>>>>>>>>>>>");
    16         
    17         String s4 = new String("hello");//s4指向堆内存地址的引用地址
    18         s4.intern();//调用intern方法,查询字符常量池是否存在字符串,如果不存在就放入字符常量池,如果存在返回地址引用
    19         String s5 = "hello";
    20         System.out.println(s4==s5);//false
    21         System.out.println("2>>>>>>>>>>>>>>>");
    22         
    23         //字符串拼接
    24         String s6_1 = "123" + "123";//在字符串常量池创建
    25         String s6_2 = new String("123") + new String("123");//在对内存中创建
    26         String s7 = "123123";
    27         System.out.println(s6_1==s6_2);//false
    28         System.out.println(s6_1==s7);//true
    29         System.out.println(s6_2==s7);//false
    30         System.out.println("3>>>>>>>>>>>>>>>");
    31         
    32         String s8 = new String("456") + "4561";//在字符串常量池创建
    33         String s9 = "4564561";
    34         System.out.println(s8==s9);//false
    35         System.out.println("4>>>>>>>>>>>>>>>");
    36         
    37         final String s10 = "abc";
    38         final String s11 = new String("abc");
    39         System.out.println("s1与s7:" + (s1 == s10));// false
    40         System.out.println("s1与s8:" + (s1 == s11));// false
    41     }
    42 
    43 }

    String.intern() 是一个 Native 方法,它的作用是:

    如果运行时常量池中已经包含一个等于此 String 对象内容的字符串,则返回常量池中该字符串的引用

    如果没有,

    JDK1.7之前(不包含1.7)的处理方式是在常量池中创建与此 String 内容相同的字符串,并返回常量池中创建的字符串的引用;

    JDK1.7以及之后的处理方式是在常量池中记录此字符串的引用,并返回该引用。

    5、基本类型包装类常量池

    Java 基本类型的包装类的大部分都实现了常量池技术,即 Byte,Short,Integer,Long,Character,Boolean。

    前面 4 种包装类默认创建了数值[-128,127] 的相应类型的缓存数据,

    Character创建了数值在[0,127]范围的缓存数据,

    Boolean 直接返回True Or False。

     两种浮点数类型的包装类 Float,Double 没有实现常量池技术。

     1 package com.javabasic.str;
     2 
     3 import java.lang.Integer.IntegerCache;
     4 
     5 /**
     6  * 默认创建了数值[-128,127] 的相应类型的缓存数据
     7  * @author wangymd
     8  *
     9  */
    10 public class IntegerTest1 {
    11 
    12     public static void main(String[] args) {
    13         Integer i1 = 40;//Java 在编译的时候会直接将代码封装成 Integer i1=Integer.valueOf(40);,从而使用常量池中的对象。
    14         Integer i2 = 40;//常量池
    15         Integer i3 = 0;
    16         Integer i4 = new Integer(40);//这种情况下会在堆中创建新的对象
    17         Integer i5 = new Integer(40);//堆内存
    18         Integer i6 = new Integer(0);
    19         
    20         Integer i7 = i2 + i3;//因为+这个操作符不适用于 Integer 对象,首先 i5 和 i6 进行自动拆箱操作,进行数值相加
    21         Integer i8 = i5 + i6;
    22         Integer i9 = new Integer(128);
    23         Integer i10 = new Integer(128);
    24         
    25         Integer i11 = Integer.valueOf(127);//IntegerCache.cache取数
    26         Integer i12 = Integer.valueOf(127);//IntegerCache.cache取数
    27         
    28         Integer i13 = Integer.valueOf(128);
    29         Integer i14 = Integer.valueOf(128);
    30 
    31         System.out.println("i1==i2   " + (i1 == i2));//true
    32         System.out.println("i1==i7   " + (i1 == i7));//true
    33         System.out.println("i1==i4   " + (i1 == i4));//false
    34         System.out.println("i4==i5   " + (i4 == i5));//false
    35         System.out.println("i4==i8   " + (i4 == i8));//false
    36         System.out.println("40==i8   " + (40 == i8));//true Integer对象无法与数值进行直接比较,所以 i4 自动拆箱转为 int 值 40,最终这条语句转为 40 == 40 进行数值比较。
    37         System.out.println("i9==i10   " + (i9 == i10));//false
    38         System.out.println("i11==i12   " + (i11 == i12));//true
    39         System.out.println("i13==i14   " + (i13 == i14));//false
    40     }
    41 
    42 }
  • 相关阅读:
    浅谈线性 Linear
    Github TinyRenderer渲染器课程实践记录
    蓝点无限UWB TDOA 低功耗标签 功耗测试
    UWB DW1000 BP30 测距代码架构
    C语言
    C语言
    张量tensor 和张量分解 tensor decomposition
    Manifold learning流行学习和谱聚类
    机器学习里面的核kernel, 维数灾难
    机器学习评价方法
  • 原文地址:https://www.cnblogs.com/wangymd/p/13213265.html
Copyright © 2011-2022 走看看