参考:深入剖析Java中的装箱和拆箱
Java中基本数据类型和包装类互转中 缓冲机制的使用
java学习笔记:装箱和拆箱,包装器和缓冲池 
Java 各 类型数据在内存中分配情况详解

一 java内存分配

这里只是在网上找的一些资料; 
Java 中的数据类型分为 
1. 基本类型(原始数据类型) byte short int long float double char boolean 
基本类型的变量持有原始值。 
2. 符合数据类型(引用类型),引用类型持有引用值(即对某个对象的引用,而非对象本身)。

一般Java在内存分配时会涉及到以下区域: 
1. 寄存器:我们在程序中无法控制 
2. 栈:存放基本类型的数据和对象的引用但对象本身不存放在栈中,而是存放在堆中 
3. 堆:存放用new产生的数据 
4. 静态域:存放在对象中用static定义的静态成员 
5. 常量池:存放常量 
6. 非RAM存储:硬盘等永久存储空间 
其中主要是堆,栈的存储。

堆,栈

  1. 函数中定义的一些基本类型的数据变量对象的引用变量都在函数的栈内存中分配。 
    栈的优势是存取速度比堆要快,仅次于直接位于CPU 的寄存器,而且数据可以共享。但是存在栈中的数据大小与生存周期必须是确定的。 
    当在一段代码块定义一个变量时,Java就在栈中 为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

  2. 堆内存用来存放由new创建的对象和数组。 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。 
    在堆中产生了一个数组或对象后,还可以 在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。 
    引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序 运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍 然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。

二 基本数据类型

这种类型是通过诸如 int a=7; 的形式来定义的,称为自动变量。这里自动变量是字面值。不是类的实例,即不是类的引用,这里并没有类的存在。a 是指向一个 int 类型的引用,指向 7 这个字面值。由于其大小确定生存期可知(这些定义在某个程序块中,程序块退出后,字段值就消失),因此存在中. 
由于栈的数据可以共享,因此 int a=3; int b=3; 这段代码,编译器首先处理 int a =3; ,先会在栈中创建一个变量为 a 的引用,然后查找有没有字面值为 3的地址,没有找到,就开辟一个存放 3 这个字面值的地址,然后将a 指向 3 的地址。接下来处理int b =3; 在创建完 b 这个引用变量后,由于栈中已经有 3 这个字面值,便将 b 指向 3 的地址。【定义变量,给变量赋值】

三 包装类数据

Java中的基本类型不是面向对象的,它们只是纯粹的数据,除了数值本身的信息之外,基本类型数据不带有其他信息或者可操作方法。这在实际使用中存在很多不足,为了解决这个不足,* 对每个基本类型都对应了一个引用的类型*,称为装箱基本类型。 

1,拆箱,装箱

装箱:根据数据创建对应的包装对象。

Integer i = new Integer (3);
Integer j = 4;//jdk1.5 之后可以通过这种方式自动装箱

拆箱:将包装类型转换为基本数据类型。

int  index2 = j.intValue();
int index1 = i;//自动拆箱

JDK1.5 为Integer 增加了一个全新的方法:public static Integer valueOf(int i) 在自动装箱过程时,编译器调用的是static Integer valueOf(int i)这个方法 于是Integer a=3; ==> Integer a=Integer.valueOf(3);

此方法与new Integer(i)的不同处在于: 
方法一调用类方法返回一个表示 指定的 int 值的 Integer 实例。方法二产生一个新的Integer 对象。

2,缓冲机制

JDK API文档中对这个新的valueOf方法有明确的解释: 
如果不需要新的 Integer 实例,则通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过缓存经常请求的值而显著提高空间和时间性能 .

查看Integer的valueOf方法的:

    public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
//static final int low = -128;
//当-128=<i<=127的时候,就直接在缓存中取出 i de Integer 类型对象
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
//否则就在堆内存中创建
return new Integer(i);
}

看出对于范围 [-128,127] 的整数,valueOf 方法做了特殊处理。采用IntegerCache.cache[i + (-IntegerCache.low)]; 这个方法。

查看 IntegerCache 类的实现为:

    private static class IntegerCache {
static final int low = -128; //最小值是固定的
static final int high;
static final Integer cache[];//cache 缓存是一个存放Integer类型的数组 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) {
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);
}
high = h; cache = new Integer[(high - low) + 1]; //初始化数组
int j = low;
//缓存区间数据
for(int k = 0; k < cache.length; k++)
//将-128~127包装成256个对象存入缓存
cache[k] = new Integer(j++);
} private IntegerCache() {}
}

IntegerCache初始化后内存中就有Integer缓冲区cache[]了,-128~127区间的int值有其对应的的包装对象。这就是 valueOf 方法真正的优化方法,当-128=

public class ZhuangXaing {

    public static void main(String[] args) {
Integer i= new Integer(12);
Integer j=12;
Integer k=Integer.valueOf(12); Integer l= new Integer(232);
Integer m=232;
Integer n=232; Double q = 232.0; System.out.println("use ==.......");
System.out.println(i==12);
System.out.println(i==j);
System.out.println(j==k); System.out.println(l==232);
System.out.println(l==m);
System.out.println(m==n); System.out.println("use equals.....");
System.out.println(m.equals(n));
System.out.println(m.equals(q)); } }

输出结果:

use ==.......
true
false
true
true
false
false
use equals.....
true
false

Integer i= new Integer(12); 是指明了在堆内存中创建对象; 
Integer j=12; 是自动装箱,调用valueOf 方法,返回return IntegerCache.cache[12 + 128], 得到的是Integer 缓冲池中的对象。Integer k=Integer.valueOf(12); 与Integer j=12; 本质上相同,指向缓冲池中同一对象。包装对象与数值比较,自动拆箱。 
而对于大于127 的数值,执行的都是return new Integer(i) 都在堆内存中,但是地址不同。

对于equals 方法比较的是数值大小:

public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

可以看出比较的 obj 如果是 Integer 的实例,则比较拆箱后数值的是否相等。否则返回false。

2,下面这段代码输出结果是什么:

public class Main {
public static void main(String[] args) { Double i1 = 100.0;
Double i2 = 100.0;
Double i3 = 200.0;
Double i4 = 200.0; System.out.println(i1==i2);
System.out.println(i3==i4);
}
//false
//false

因为Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。

其他的包装器: 
Boolean: (全部缓存) 
Byte: (全部缓存)

Character ( <=127 缓存) 
Short (-128~127 缓存) 
Long (-128~127 缓存)

Float (没有缓存) 
Doulbe (没有缓存)

3,下面这段代码输出结果是什么:

public class Main {
public static void main(String[] args) { Boolean i1 = false;
Boolean i2 = false;
Boolean i3 = true;
Boolean i4 = true; System.out.println(i1==i2);
System.out.println(i3==i4);
}
}

先看Boolean 类的源码 ,valueOf 方法的实现:

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

而其中的 TRUE 和FALSE又是什么呢?在Boolean中定义了2个静态成员属性:

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

    /**
* The <code>Boolean</code> object corresponding to the primitive
* value <code>false</code>.
*/
public static final Boolean FALSE = new Boolean(false);

由此可知上面代码输出都为true .

Java中基本数据类型和包装类的更多相关文章

  1. java中基本数据类型、包装类及字符串之间的相互转换

    基本数据类型:不支持面向对象的编程机制(没有属性和方法),即不支持面向对象,之所以提供8中基本数据类型,是为了方便常规数据的处理. 包装类:通过包装类可以将基本数据类型的值包装为引用数据类型的对象,使 ...

  2. Java基础(34):Java中基本数据类型的包装类(主要为了不同数据类型之间更方便的进行转换)(Wrapper类)

    相信各位小伙伴们对基本数据类型都非常熟悉,例如 int.float.double.boolean.char 等.基本数据类型是不具备对象的特性的,比如基本类型不能调用方法.功能简单...,为了让基本数 ...

  3. Java中关于数据类型的一些问题

    Java中关于数据类型的一些问题 总结一下最近笔试遇到的一些关于Java中数据类型的一些问题. 虽然比较基础,但在实际做题却很容易出错的点,而且往往这些题出错了会给面试官很不好的感觉:你的基础不好. ...

  4. Java中的基本类型和包装类

    Java中基本数据类型与包装类型有   基本类型     包装器类型   boolean Boolean char Character int Integer byte Byte short Shor ...

  5. Java中特殊的类——包装类

    Java中特殊的类--包装类 包装类就是将基本数据类型封装在类中. 1.包装类 (1)自定义包装类 将基本数据类型包装成一个类对象的本质就是使用Object进行接收处理. 此时IntDemo类就是in ...

  6. Java中的数据类型及相互转换方法

    本文主要讲解两个部分: 一.Java中的数据类型有哪些? 二.数字类型和字符串类型相互转换的方法? 一.Java中的数据类型有哪些: Java中的数据类型有:基本数据类型和引用数据类型: 基本数据类型 ...

  7. java中的数据类型,运算符,字符串,输入输出,控制流,大数值,数组; 《java核心技术卷i》 第三章:java基本程序结构;

    <java核心技术卷i> 第三章:java基本程序结构: 每次看书,去总结的时候,总会发现一些新的东西,这次对于java的数组有了更深的了解: java中的数据类型,运算符,字符串,输入输 ...

  8. 讲说问题:|和||的区别以及&和&&的区别。2、Java中的数据类型分几类?基本数据类型有哪些?

    |和||的区别以及&和&&的区别. |或 为或运算 判断为逻辑或 || 为短路或 只有逻辑判断 当左侧为真不再继续判断 &与 为与运算 判断为逻辑与 && ...

  9. Java中基本数据类型byte的溢出问题

    Java中基本数据类型byte的溢出问题 问题源于:https://www.cnblogs.com/HuoHua2020/p/12326631.html 定义两个byte类型的数据,将其之和赋值给一个 ...

随机推荐

  1. mybatis if test 解决页面 升序和降序的问题

    <if test="status !=null and status !='' and status =='1'.toString()"> ORDER BY tag.c ...

  2. Java8 Lambda/Stream使用说明

    一.Stream流1. 流的基本概念 1.1 什么是流?流是Java8引入的全新概念,它用来处理集合中的数据,暂且可以把它理解为一种高级集合.众所周知,集合操作非常麻烦,若要对集合进行筛选.投影,需要 ...

  3. memcache与mysql的连接

    MySQL官方在5.6版本以上有一个与memcache连接的插件,名字叫做innodb_memcache. 1),没有安装过MySQL的,可以在CMAKE的时候加入:-DWITH_INNODB_MEM ...

  4. solr学习-基础环境搭建(一)

    目前网上关于solr6.+的安装教程很少,有些6.0之前的教程在应用到6.+的版本中出现很多的问题,所以特别整理出来这一片文章,希望能给各位码农一些帮助! 很少写些文章,如有不对的地方,还希望多多指导 ...

  5. android studio gradle 两种更新方法更新

    android studio gradle 两种更新方法更新 第一种.Android studio更新 第一步:在你所在项目文件夹下:你项目根目录gradlewrappergradle-wrapper ...

  6. CSS3学习系列之布局样式(二)

    使用盒布局 在CSS3中,通过box属性来使用盒布局,例子如下: <!DOCTYPE html> <html lang="en"> <head> ...

  7. Watson Explorer Analytical Components 3 - use case scenarios

    The followings are the user case scenarios that WEX can be used for generating value. 1.Customer Ins ...

  8. 搭建ES6运行环境

    当ES5还没有完全普及时,ES6就接踵而来了,2015年6月17日,ECMAScript 6发布正式版本,即ECMAScript 2015,我们也简称它为ES6或ES2015.在发布之后的将近一年内, ...

  9. 业余草推荐18个Java开源免费的CMS系统

    1.InfoGlue infoglue是一个高级的.可扩展的.健壮的内容管理系统,完全用Java开发.重要的功能包括完全支持多语言,站点之间良好的重用,以及广泛的集成能力. 该项目主页:http:// ...

  10. IDEA使用01 创建java项目、创建web项目

    注意:本教程使用的开发环境是:(专业版) 1 创建javaSE项目 1.1 file -> new -> project 注意:如果是第一次使用,就需要配置 project SDK  , ...