Java包装类的缓存机制原理实例详解

这篇文章主要介绍了Java包装类的缓存机制原理实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

java 包装类的缓存机制,是在Java 5中引入的一个有助于节省内存、提高性能的功能,只有在自动装箱时有效

Integer包装类

举个栗子:

Integer a = 127;
Integer b = 127;
System.out.println(a == b);

这段代码输出的结果为true

使用自动装箱将基本类型转为封装类对象这个过程其实底层实现是调用封装类的valueOf方法:

Integer a =127; 相当于 Integer a = Integer.valueOf(127);

看一下Integer的valueOf方法:

public static Integer valueOf(int i) {
  if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
  return new Integer(i);
}

如果入参 i 大于等于IntegerCache.low或者小于等于IntegerCache.high),就从IntegerCache中获取对象

看一下IntegerCache:

private static class IntegerCache {
  static final int low = -128;
  static final int high;
  static final Integer cache[];

  static {
    // high value may be configured by property
    int h = 127;
    String integerCacheHighPropValue =
      sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    if (integerCacheHighPropValue != null) {
      try {
        int i = parseInt(integerCacheHighPropValue);
        i = Math.max(i, 127);
        // Maximum array size is Integer.MAX_VALUE
        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
      } catch( NumberFormatException nfe) {
        // If the property cannot be parsed into an int, ignore it.
      }
    }
    high = h;

    cache = new Integer[(high - low) + 1];
    int j = low;
    for(int k = 0; k < cache.length; k++)
      cache[k] = new Integer(j++);

    // range [-128, 127] must be interned (JLS7 5.1.7)
    assert IntegerCache.high >= 127;
  }

  private IntegerCache() {}
}

默认范围为:-128到127之间,范围的最大值可以通过java.lang.Integer.IntegerCache.high设置,通过for循环将范围内的数据实例化为Integer对象放到cache数组里

在测试一下:

Integer a = 128;
Integer b = 128;
System.out.println(a == b);

输出结果为false,所以如果没有指定cache最大值时,在-128到127之间使用自动装箱时,会使用缓存

Byte包装类

再举个栗子:

public static void main(String[] args) {
  Byte a = 127;
  Byte b = 127;
  System.out.println(a == b); //true
}

由于Byte范围在-128到127之间,所以Byte的valueOf都是从ByteCache缓存中获取的

public static Byte valueOf(byte b) {
  final int offset = 128;
  return ByteCache.cache[(int)b + offset];
}

ByteCache类:

private static class ByteCache {
  private ByteCache(){}

  static final Byte cache[] = new Byte[-(-128) + 127 + 1];

  static {
    for(int i = 0; i < cache.length; i++)
      cache[i] = new Byte((byte)(i - 128));
  }
}

与IntegerCache相比,ByteCache的最大值是不能修改的就是127

Short包装类

public static Short valueOf(short s) {
  final int offset = 128;
  int sAsInt = s;
  if (sAsInt >= -128 && sAsInt <= 127) { // must cache
    return ShortCache.cache[sAsInt + offset];
  }
  return new Short(s);
}

ShortCache类:

private static class ShortCache {
  private ShortCache(){}

  static final Short cache[] = new Short[-(-128) + 127 + 1];

  static {
    for(int i = 0; i < cache.length; i++)
      cache[i] = new Short((short)(i - 128));
  }
}

ShortCache的最大值也不可以修改,范围只能在-128 ~ 127之间

Long包装类的valueOf方法和LongCache类与Short包装类的实现一致,范围也是只能在-128 ~ 127之间

Character包装类

valueOf方法:

public static Character valueOf(char c) {
  if (c <= 127) { // must cache
    return CharacterCache.cache[(int)c];
  }
  return new Character(c);
}

CharacterCache类:

private static class CharacterCache {
  private CharacterCache(){}

  static final Character cache[] = new Character[127 + 1];

  static {
    for (int i = 0; i < cache.length; i++)
      cache[i] = new Character((char)i);
  }
}

Character的缓存范围在0 ~ 127之间

Boolean包装类

valueOf方法:

public static Boolean valueOf(boolean b) {
  return (b ? TRUE : FALSE);
}

TRUE跟FALSE都是static final修饰的静态变量

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

Float包装类 & Double包装类

valueOf方法:

public static Float valueOf(float f) {
  return new Float(f);
}
public static Double valueOf(double d) {
  return new Double(d);
}

Float和Double没有使用缓存,直接new的对象

总结:

java的包装类中:Byte,Short,Integer,Long,Character使用static代码块进行初始化缓存,其中Integer的最大值可以通过java.lang.Integer.IntegerCache.high设置;Boolean使用static final实例化的对象;Float和Double直接new的对象没有使用缓存

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2019-12-22

Java基本类型与包装类详细解析

Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型. 1.整数:包括int,short,byte,long ,初始值为0 2.浮点型:float,double ,初始值为0.0 3.字符:char ,初始值为空格,即'' ",如果输出,在Console上是看不到效果的. 4.布尔:boolean ,初始值为false 基本型别 大小 最小值 最大值 boolean ----- ----- ------ char 16-bit Unicode 0

Java基本类型包装类概述与Integer类、Character类用法分析

本文实例讲述了Java基本类型包装类概述与Integer类.Character类用法.分享给大家供大家参考,具体如下: 基本类型包装类概述 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据. 常用的操作之一:用于基本数据类型与字符串之间的转换. 基本类型和包装类的对应 Byte,Short,Integer,Long,Float,Double,Character,Boolean Integer类 为了让基本类型的数据进行更多的操作,Java就为每种基本类型提供了对应的包装

详解Java包装类及自动装箱拆箱

Java包装类 基本类型 大小 包装器类型 boolean / Boolean char 16bit Boolean byte 8bit Byte short /16bit Short int 32bit Integer long 64bit Long float 32bit Float double 64bit Double void / Void Java 的包装类有两个主要的目的: Java包装类将基本数据类型的值"包装"到对象中,对基本数据类型的操作变为了对对象进行操作,从而使

java中Integer包装类装箱的一个细节详解

前言 java有八个基本数据类型,每个都有对应的一个包装类,比如int对应的Integer. Integer 是int的包装类型,数据类型是类,初值为null,从jdk1.5开始,java引入了自动拆装箱,可以直接进行形如Integer i = 20形式的赋值,编译器会自动将其转换为Integer i = Integer.valueOf(20)进行装箱,拆箱则是将int j = i的形式转换成了int j = i.intValue() . 装箱有个细节,如果不注意很容易出错,来看一下: Inte

Java中包装类介绍与其注意事项

前言 大家都知道在Java中,除了8种基本数据类型外,其他的都是引用类型.使用引用类型是为了更好地贯彻面向对象的思想,那为什么还要保留8种基本数据类型呢? 这其实更多地是照顾程序员的习惯.为了既照顾程序员的习惯,同时又能全面贯彻面向对象编程的思想,Java中引入了包装类机制. 所谓的包装类就是为8种基本数据类型分别定义了相应的引用类型,其对应关系如下: 显然,除了int及char外,其余的包装类都是将对应的基本数据类型的首字母大写即可. 那为什么要引入包装类呢?前面已经说过,是为了全面贯彻面向对

JAVA包装类及自动封包解包实例代码

复制代码 代码如下: public class Wrapper {     public static void main(String[] args) {         int i = 500;         Integer t = new Integer(i);         int j = t.intValue();         String s = t.toString();         System.out.println(t);         Integer t1 =

解决Java包装类比较时遇到的问题

前言 本文主要给大家介绍了关于Java包装类在比较时遇到的一些问题的解决方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 例1: Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e= 321; Integer f= 321; Long g = 3L; System.out.println(c == d); //1 System.out.println(e == f); //2 Syste

Java基本数据类型与对应的包装类(动力节点java学院整理)

Java是面向对象的编程语言,包装类的出现更好的体现这一思想. 其次,包装类作为类是有属性有方法的,功能比基本数据类型要强大. Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型. 1.整数:包括int,short,byte,long ,初始值为0 2.浮点型:float,double ,初始值为0.0 3.字符:char ,初始值为空格,即'' ",如果输出,在Console上是看不到效果的. 4.布尔:boolean ,初始值为false 注

Java中Object toString方法简介_动力节点Java学院整理

一.Object类介绍  Object类在Java里面是一个比较特殊的类,JAVA只支持单继承,子类只能从一个父类来继承,如果父类又是从另外一个父类继承过来,那他也只能有一个父类,父类再有父类,那也只能有一个,JAVA为了组织这个类组织得比较方便,它提供了一个最根上的类,相当于所有的类都是从这个类继承,这个类就叫Object.所以Object类是所有JAVA类的根基类,是所有JAVA类的老祖宗.所有的类,不管是谁,都是从它继承下来的. 二.toString方法介绍  一个字符串和另外一种类型连接

Java类的继承实例详解(动力节点Java学院整理)

一.你了解类吗? 在Java中,类文件是以.java为后缀的代码文件,在每个类文件中最多只允许出现一个public类,当有public类的时候,类文件的名称必须和public类的名称相同,若不存在public,则类文件的名称可以为任意的名称(当然以数字开头的名称是不允许的). 在类内部,对于成员变量,如果在定义的时候没有进行显示的赋值初始化,则Java会保证类的每个成员变量都得到恰当的初始化: 1)对于  char.short.byte.int.long.float.double等基本数据类型的

Java IO流体系继承结构图_动力节点Java学院整理

Java IO体系结构看似庞大复杂,其实有规律可循,要弄清楚其结构,需要明白两点: 1. 其对称性质:InputStream 与 OutputStream, Reader 与 Writer,他们分别是一套字节输入-输出,字符输入-输出体系 2. 原始处理器(适配器)与链接流处理器(装饰器) 其结构图如下: Reader-Writer体系 1. 基类 InputStream与OutputStream是所有字节型输入输出流的基抽象类,同时也是适配器(原始流处理器)需要适配的对象,也是装饰器(链接流处

Java线程安全的常用类_动力节点Java学院整理

线程安全类 在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的.在jdk1.2之后,就出现许许多多非线程安全的类. 下面是这些线程安全的同步的类: vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用.在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的. statck:堆栈类,先进后出 hashtable:就比hashmap多了个线程安全 除了这些之外,其他的集合大都是非线程安全的类和接口. 线程安全的类其方法是同步

Java JVM原理与调优_动力节点Java学院整理

JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回收堆和一个存储方法域. JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行.是运行Java应用最底层部分. JDK(Java Development kit) 整个Java的核心,包括了Java运行环境(Java Runtime E

Java数据结构与算法之选择排序(动力节点java学院整理)

每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完. 代码 public class ChoseSort { //constructor without parameters public ChoseSort(){}; //constructor with parameters public int[] ChoseSort(int[] intArr){ for(int i=0;i<intArr.length-1;i++){ int

Java的几个重要版本_动力节点Java学院整理

java几个重大版本 java从1995年发布到现在,也走过18年了,个人认为,其中几个java版本都肩负着重大使命,影响甚远: jdk1.0 1995年5月23日诞生,Oak语言改名为Java,并提出"Write Once ,Run anywhere": jdk1.2  1999年6月发布,将java划分为J2SE,J2ME,J2EE三大平台: jdk1.4 主要是性能提升,在2000年时候JAVA成为世界上最流行的电脑语言,跟这个版本离不开关系,估计国内还有大量的java应用是运行

Java concurrency之AtomicLongArray原子类_动力节点Java学院整理

AtomicLongArray介绍和函数列表  AtomicLongArray函数列表 // 创建给定长度的新 AtomicLongArray. AtomicLongArray(int length) // 创建与给定数组具有相同长度的新 AtomicLongArray,并从给定数组复制其所有元素. AtomicLongArray(long[] array) // 以原子方式将给定值添加到索引 i 的元素. long addAndGet(int i, long delta) // 如果当前值 =

Java动态代理机制详解_动力节点Java学院整理

class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件,取出二进制数据,加载到内存中,解析.class 文件内的信息,生成对应的 Class对象: class字节码文件是根据JVM虚拟机规范中规定的字节码组织规则生成的.具体class文件是怎样组织类信息的,可以参考 此博文:深入理解Java Class文件格式系列.或者是Java虚拟机规范. 下面通过一段代