Java中基本数据类型和包装类
参考:深入剖析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存储:硬盘等永久存储空间
其中主要是堆,栈的存储。
堆,栈
函数中定义的一些基本类型的数据变量和对象的引用变量都在函数的栈内存中分配。
栈的优势是存取速度比堆要快,仅次于直接位于CPU 的寄存器,而且数据可以共享。但是存在栈中的数据大小与生存周期必须是确定的。
当在一段代码块定义一个变量时,Java就在栈中 为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。堆内存用来存放由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中基本数据类型和包装类的更多相关文章
- java中基本数据类型、包装类及字符串之间的相互转换
基本数据类型:不支持面向对象的编程机制(没有属性和方法),即不支持面向对象,之所以提供8中基本数据类型,是为了方便常规数据的处理. 包装类:通过包装类可以将基本数据类型的值包装为引用数据类型的对象,使 ...
- Java基础(34):Java中基本数据类型的包装类(主要为了不同数据类型之间更方便的进行转换)(Wrapper类)
相信各位小伙伴们对基本数据类型都非常熟悉,例如 int.float.double.boolean.char 等.基本数据类型是不具备对象的特性的,比如基本类型不能调用方法.功能简单...,为了让基本数 ...
- Java中关于数据类型的一些问题
Java中关于数据类型的一些问题 总结一下最近笔试遇到的一些关于Java中数据类型的一些问题. 虽然比较基础,但在实际做题却很容易出错的点,而且往往这些题出错了会给面试官很不好的感觉:你的基础不好. ...
- Java中的基本类型和包装类
Java中基本数据类型与包装类型有 基本类型 包装器类型 boolean Boolean char Character int Integer byte Byte short Shor ...
- Java中特殊的类——包装类
Java中特殊的类--包装类 包装类就是将基本数据类型封装在类中. 1.包装类 (1)自定义包装类 将基本数据类型包装成一个类对象的本质就是使用Object进行接收处理. 此时IntDemo类就是in ...
- Java中的数据类型及相互转换方法
本文主要讲解两个部分: 一.Java中的数据类型有哪些? 二.数字类型和字符串类型相互转换的方法? 一.Java中的数据类型有哪些: Java中的数据类型有:基本数据类型和引用数据类型: 基本数据类型 ...
- java中的数据类型,运算符,字符串,输入输出,控制流,大数值,数组; 《java核心技术卷i》 第三章:java基本程序结构;
<java核心技术卷i> 第三章:java基本程序结构: 每次看书,去总结的时候,总会发现一些新的东西,这次对于java的数组有了更深的了解: java中的数据类型,运算符,字符串,输入输 ...
- 讲说问题:|和||的区别以及&和&&的区别。2、Java中的数据类型分几类?基本数据类型有哪些?
|和||的区别以及&和&&的区别. |或 为或运算 判断为逻辑或 || 为短路或 只有逻辑判断 当左侧为真不再继续判断 &与 为与运算 判断为逻辑与 && ...
- Java中基本数据类型byte的溢出问题
Java中基本数据类型byte的溢出问题 问题源于:https://www.cnblogs.com/HuoHua2020/p/12326631.html 定义两个byte类型的数据,将其之和赋值给一个 ...
随机推荐
- Quirks模式是什么?它和Standards模式有什么区别
从IE6开始,引入了Standards模式,标准模式中,浏览器尝试给符合标准的文档在规范上的正确处理达到在指定浏览器中的程度. 在IE6之前CSS还不够成熟,所以IE5等之前的浏览器对CSS的支持很差 ...
- Zookeeper:分布式程序的基石
一.目录 1.zookeeper是什么? 2.安装.配置.启动.监控 3.javaApi基础用法 4.应用场景 5.CAP理论/paxos算法 二.zookeeper简介 官方版:zookeeper是 ...
- 数独小算法,测试通过(Java)
class SudokuMatrix { private int[][] matrix = new int[][] { {0, 5, 0, 6, 0, 1, 0, 0, 0}, {0, 0, 7, 0 ...
- gdb常用命令及使用gdb调试多进程多线程程序
一.常用普通调试命令 1.简单介绍GDB 介绍: gdb是Linux环境下的代码调试⼯具.使⽤:需要在源代码⽣成的时候加上 -g 选项.开始使⽤: gdb binFile退出: ctrl + d 或 ...
- tomcat运行war包报错,找不到context-root文件
今天在部署项目的时候遇到了这个问题,查看Tomcat日志/logs/cataline.out这个文件. 里面有一句:can not open .....[context-root.xml], 进过很长 ...
- phpexcl导出数据
<?php public function export_do_one(){ //excel 导出数据 import('ORG.Util.Page_new');// 导入分页类 ,修改了原来的P ...
- 10.解决VUEX刷新的时候出现数据消失
通常,我们在使用vue编写页面时,会需要使用vuex在组件间传递(或者说共同响应)同一个数据的变化.例如:用户的登录信息. 下面,我们使用传递用户登录信息的例子来一步步解决这个问题. 首先,我们的第一 ...
- Java集合框架梳理(含经典面试题)
Java Collections Framework是Java提供的对集合进行定义,操作,和管理的包含一组接口,类的体系结构. 1. 整体框架 Java容器类库一共有两种主要类型:Collection ...
- js-ES6学习笔记-Set结构和Map结构
http://www.cnblogs.com/lonhon/ 1.ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set ...
- C#深入学习 ----多线程学习(一)第一天学习
学习最好的方法就是总结,并写下来,能让别人看懂,自己肯定是掌握了的. 针对软件开发,一直停留在能做的层次,今天得到大牛指点,觉得有必要对这门技术深入学习. 翻阅园内各大神的文章,收益匪浅,在这里做下总 ...