本着重新学习(看到什么复习什么)的原则,这一篇讲的是JAVA的封箱和拆箱。看了诸位大神的解释后详细的查了一些东西,记录下来,也感谢各位在网络上的分享!!!

参考链接如下:https://www.cnblogs.com/vilionzhan/p/8552067.html

https://www.cnblogs.com/xiaozhang2014/p/5347407.html

https://blog.csdn.net/tangyuan_sibal/article/details/86566687

https://www.cnblogs.com/cocoxu1992/p/10644217.html

(一)JAVA的基本数据类型及其包装器类

在总结封箱和拆箱之前先要了解JAVA的基本数据类型及其包装器类,表格如下:

数据类型 所占字节数 所占位数 取值范围 默认值 包装器类 缓存
byte(字节) 1 8 -128 ~ 127 0 Byte -128 ~ 127
short(短整型) 2 16 -2^15~2^15-1 0 Short -128 ~ 127
int(整型) 4 32 -2^31~2^31-1 0 Integer -128 ~ 127
long(长整型) 8 64 -2^63~2^63-1 0 Long -128 ~ 127
float(浮点型) 4 32 -3.40292347E+38-3.40292347E+38 0.0f Float
double(双精度) 8 64 -1.79769313486231570E+308-1.79769313486231570E+308 0.0d Double
char(字符型) 2 16 ‘ \u0000 - u\ffff ’  ‘\u0000 ’ Char 0 ~ 127
boolean(布尔型) - 1 true/false false Boolean true/false

如下为代码,由代码可得JAVA基本数据类型的一些定值。

package com.day_1.excercise_1;public class DataType {public static byte byteType;public static short shortType;public static int intType;public static long longType;public static float floatType;public static double doubleType;public static char charType;public static boolean booleanType;public static void main(String[] args) {System.out.println("byte\r\n位数:" + Byte.SIZE + ";"+ "字节数:"+Byte.SIZE/8+";"+ "默认值:" + byteType + ";"+ "数据范围:" + Byte.MIN_VALUE + " ~ " + Byte.MAX_VALUE);System.out.println("short\r\n位数:" + Short.SIZE+ ";"+ "字节数:"+Short.SIZE/8 + ";"+ "默认值:" + shortType + ";"+ "数据范围:" + Short.MIN_VALUE + " ~ " + Short.MAX_VALUE);System.out.println("int\r\n位数:" + Integer.SIZE+ ";"+ "字节数:"+Integer.SIZE/8 + ";"+ "默认值:" + intType + ";"+ "数据范围:" + Integer.MIN_VALUE + " ~ " + Integer.MAX_VALUE);System.out.println("long\r\n位数:" + Long.SIZE+ ";"+ "字节数:"+Long.SIZE/8 + ";"+ "默认值:" + longType + ";"+ "数据范围:" + Long.MIN_VALUE + " ~ " + Long.MAX_VALUE);System.out.println("float\r\n位数:" + Float.SIZE+ ";"+ "字节数:"+Float.SIZE/8 + ";"+ "默认值:" + floatType + ";"+ "数据范围:" + Float.MIN_VALUE + " ~ " + Float.MAX_VALUE);System.out.println("double\r\n位数:" + Double.SIZE+ ";"+ "字节数:"+Double.SIZE/8 + ";"+ "默认值:" + doubleType + ";"+ "数据范围:" + Double.MIN_VALUE + " ~ " + Double.MAX_VALUE);System.out.println("char\r\n位数:" + Character.SIZE+ ";"+ "字节数:"+Character.SIZE/8 + ";"+ "默认值:" + charType + ";"+ "数据范围:" + Character.MIN_VALUE + " ~ "+ Character.MAX_VALUE);System.out.println("boolean\r\n"+ "默认值:" + booleanType + ";"+ "数据范围:" + Byte.MIN_VALUE + " ~ " + Byte.MAX_VALUE);}
}

下图为代码运行结果:

(二)概念解析和源码分析

1.包装类

首先看一下Integer类的说明:


java.lang.IntegerThe Integer class wraps a value of the primitive type int in an object. An object of type Integer contains a single field whose type is int. In addition, this class provides several methods for converting an int to a String and a String to an int, as well as other constants and methods useful when dealing with an int. Implementation note: The implementations of the "bit twiddling" methods (such as highestOneBit and numberOfTrailingZeros) are based on material from Henry S. Warren, Jr.'s Hacker's Delight, (Addison Wesley, 2002).
Since:JDK1.0Author:Lee BoyntonArthur van HoffJosh BlochJoseph D. Darcy

可见“该类提供了几种将int转换为字符串和字符串转换为int的方法,以及处理int时有用的其他常量和方法。”,归纳也就是说,包装类内包含着各种基本数据类型的相关属性和方法等,除此之外将基本类型变成了对象类型。

2.自动装包与拆包

自动装包与拆包是JDK 1.5(后更名为JDK 5.0)出现的新内容,实现的就是在基本数据类型和对应的包装类之间的转换的功能。即自动装包为将基本类型自动转换为包装类,同理自动拆包为将包装类自动转换为基本类型。

3.堆内存,栈内存,方法区

堆内存:JAVA堆被是被所有线程共享的一块内存区域,在JAVA虚拟机启动时创建JAVA的堆,堆内存放的是由new创建的对象实例和数组,JAVA堆是由JAVA虚拟机的自动垃圾回收器管理。堆内存的分配方式类似于链表。

栈内存:在函数中定义的基本类型的变量和对象的引用变量都是在函数的栈内存分配。

方法区:也叫做静态区,同堆一样是被所有的线程共享的。在方法区中包含所有的class和static变量。(关于这个“class”我仔细查了一下,类的实例方法会存在方法区中,并不会随创建对象而随对象保存在堆中,即class对象依然是放在堆中,而类的方法等均存储在方法区。如果有不对的地方,麻烦一定指点,这个点我一直比较困扰,多谢!!!)

总结下来的话就是:在针对基本数据类型时,(int a = 1;)是直接在栈中分配内存的,而(Integer a = new Integer(1);)则分为两部分,Integer对象在堆内存中,而该Integer对象的引用变量是在栈内存中。相当于在堆中产生了一个Integer对象后,还在栈中定义了一个名为a的变量,并且栈中的这个变量a的取值等于该Integer对象在堆内存指向的首地址,栈中的这个变量a就变成了该Integer对象的引用变量。而在被释放的问题上,引用变量在程序运行到作用域外便被释放;对象只在没有引用变量指向时,才变成垃圾,但是仍会在短时间内占用内存,而后在某一个时间被垃圾回收器释放。

4.装箱,拆箱

由于JAVA对某些经常使用的基本数据类型采用缓存机制,当该数据存在在缓存范围内时,可以直接从缓存中获取,从而提高高JAVA程序的执行性能。但在基本数据类型中会分为两类,Integer,Short,Byte,Character,Long是有缓存范围的,Double,Float是没有缓存范围的,即每一个创建的对象都不同。来分别看一下Integer类型和Double类型的valueOf方法的具体实现。

     /*** Returns an {@code Integer} instance representing the specified* {@code int} value.  If a new {@code Integer} instance is not* required, this method should generally be used in preference to* the constructor {@link #Integer(int)}, as this method is likely* to yield significantly better space and time performance by* caching frequently requested values.** This method will always cache values in the range -128 to 127,* inclusive, and may cache other values outside of this range.** @param  i an {@code int} value.* @return an {@code Integer} instance representing {@code i}.* @since  1.5*/public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}/*** Returns a {@code Double} instance representing the specified* {@code double} value.* If a new {@code Double} instance is not required, this method* should generally be used in preference to the constructor* {@link #Double(double)}, as this method is likely to yield* significantly better space and time performance by caching* frequently requested values.** @param  d a double value.* @return a {@code Double} instance representing {@code d}.* @since  1.5*/public static Double valueOf(double d) {return new Double(d);}

由上述代码注释和代码区别可以看出Integer类型的valueOf方法在处理时会由于该方法很可能被频繁使用,故会始终缓存范围为(-128 to 127)的数值,而Double类型的valueOf方法在处理中不会进行缓冲区的范围值判断。并且在Integer的valueOf方法中可以发现缓存范围的定义,即IntegerCache内部类。其中详细说明了缓存支持范围的自动装箱过程。

    /*** Cache to support the object identity semantics of autoboxing for values between* -128 and 127 (inclusive) as required by JLS.** The cache is initialized on first usage.  The size of the cache* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.* During VM initialization, java.lang.Integer.IntegerCache.high property* may be set and saved in the private system properties in the* sun.misc.VM class.*/private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint 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_VALUEh = 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() {}}

4.数值比较

“==”和equals()在比较时也是有区别的。

在“==”的数值比较中,如果同是包装类型(如:Integer)在比较时遵循缓存范围的数值,即数值范围内对象相同,范围外对象不同,但若该包装类型没有缓存范围(如:Double),则创建时一定是两个不同的对象,故比较结果一定不相等;如果是一个包装类型和一个基本数据类型之间比较(如:Integer和int进行加减乘除)会将该包装类型进行拆箱,故数值比较上一定相同。

在equals()的数值比较中,除了判断内容是否相同以外还要判断类型是否相同,因为该方法使用时使用的是包装类型.equals(基本数据类型)的方式,故会将该基本数据类型进行装箱,从而变成两个包装类型的数值比较,那么类型相同为true,而后便是判断数值是否相同。

而在不同类型的比较时会根据不同情况进行分析,具体分析方法包括上述所有方法,如下(Dv5 == (Iv10 + Iv11))中,Dv5是Double(包装类型),Iv10是Integer(包装类型),Iv11是int(基本数据类型),在((Iv10 + Iv11),后文中用Iv12接收结果,方便描述)中遵循包装类型和基本数据类型的加减乘除过程会先将包装类型进行拆箱后进行,而此时(Dv5 == Iv12)时,也会遵循包装类型和基本数据类型进行数据比较,故结果为true。而(Dv5.equals(Iv10 + Iv11))结果为false的原因更是一目了然,因为上述装换后,Dv5为包装类型,而Iv10和Iv11的加和结果Iv12是一个基本数据类型,故类型不相同,equals()判断固然会为false。

如下为一些代码测试,很多值都是在缓存范围值的临界线上,方便理解范围的概念:

package com.day_1.excercise_1;public class DataSize {public static void main(String args[]) {Integer Iv1 = -128;Integer Iv2 = -128;Integer Iv3 = 128;Integer Iv4 = 128;System.out.println(Iv1 == Iv2); // trueSystem.out.println(Iv3 == Iv4); // falseInteger Iv5 = 127;int Iv6 = 127;int Iv7 = 1;Integer Iv8 = 128;int Iv9 = 128;System.out.println(Iv5 == Iv6); // trueSystem.out.println(Iv4 == (Iv6 + Iv7)); // trueSystem.out.println(Iv5.equals(Iv6)); // trueSystem.out.println(Iv8.equals(Iv9)); // trueDouble Dv1 = 100.0;Double Dv2 = 100.0;double Dv3 = 100;double Dv4 = 100;System.out.println(Dv1 == Dv2); // falseSystem.out.println(Dv3 == Dv4); // trueSystem.out.println(Dv1.equals(Dv3)); // trueInteger Iv10 = 100;int Iv11 = 100;Double Dv5 = 200d;System.out.println(Dv5 == (Iv10 + Iv11)); // trueSystem.out.println(Dv5.equals(Iv10 + Iv11)); // false}
}

如文首所提,我只是将很多我查看到的问题的解释尽量用我的理解说出来,所以大神们的文章各自都非常有价值,我只是进行了总结归纳,如果我说的不太明确,各位大神的原文链接都在文首,一定能解答你的疑惑,此外,如果有错误还请一定指教,谢谢!!!

JAVA基础复习(一)相关推荐

  1. Java基础复习笔记系列 九 网络编程

    Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...

  2. Java基础复习笔记系列 七 IO操作

    Java基础复习笔记系列之 IO操作 我们说的出入,都是站在程序的角度来说的.FileInputStream是读入数据.?????? 1.流是什么东西? 这章的理解的关键是:形象思维.一个管道插入了一 ...

  3. 2020604 Java基础复习

    2020/6/4 Java基础复习 Java特性和优势 1.简单性: Java是在C++的语法的基础再"减减".没有头文件,没有指针,也不用分配内存,所以相对来说比较简单; 2.面 ...

  4. Java基础复习(六)

    Java基础复习(六) 常见关键字总结 1.final关键字 final用来修饰类.方法和变量. (1)final修饰的类不能被继承,而且final修饰的类中,所有成员方法会被默认为final方法,不 ...

  5. Java基础复习-常用类

    Java基础复习-常用类 本文仅对学习过程中所缺java知识点的查缺补漏复习 String 代表字符串.Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现. St ...

  6. Java基础复习-八大基本数据类型-内存模型-基本算法-网络编程

    Java基础 数据类型: 基本数据类型: 整数型:byte short int long(数值型) 浮点型: float double(数值型) 字符型:char 布尔型:boolean 引用数据类型 ...

  7. java基础复习(练习写博客)

    文章目录 Java特性和优势 java三大版本 JDK.JRE.JVM(从前到后包含) Java开发环境搭建步骤 Java程序运行机制 IDE Java基础语法 一.注释.标识符.关键字 二.数据类型 ...

  8. Java基础复习总结笔记(上)

    前言 对Java部分基础知识进行复习总结,没事可以看看. 目录 一.基础语法 1.1 Java名词 1.2 Java关键字 1.3 基本数据类型(4类8种) (1)整数类型 (2)浮点类型 (3)字符 ...

  9. Java 基础复习实践 --- Hashcode Equals

    虽然很多知识点书籍都有整理,但是记性总是不好,所以决定将一些细小容易混淆的概念,通过简单的 Demo 实践,加深复习.特此开一个坑,坚持就是胜利. 本章内容主要为了理解以下几个知识点: equals( ...

  10. Java基础复习(1) 为什么在java中我们要将main定义为一个static方法?

    2015-10-20 以前学习java知识,只是跟着用到的代码跳着学了些,学的不全还错漏成片--恩,好惨! 思来想去,是必须要好好复习加整理下,不然写出来的东西真没法读了.所以,就从今儿起一点一点的啃 ...

最新文章

  1. Ubuntu 14.04 64bit上安装有道词典Linux版本
  2. C++ 内存泄漏检测:valgrind和AddressSanitizer
  3. cdh中使用hue使用教程_我可以在户外使用Philips Hue灯泡吗?
  4. 不止代码:最长上升序列
  5. cygwin下的gcc-4.7.1编译心得
  6. RTOS 任务间互斥的难题
  7. linux线程负载,linux 排查cpu负载过高异常(转载)
  8. 再问数据中台 - 数据中台的典型架构是怎样的?
  9. 泽尼克多项式 matlab,zernike多项式 ---matlab程序 ---arrayfun.m函数
  10. 安卓图片框架:universal-image-loader的高速使用
  11. 元组怎么变成列表_Python入门教程笔记(四)元组(tuple)及字典(dict)
  12. R语言大作业(全国2000-2019年人口各项数据分析)
  13. 推荐项目| 微信小程序富文本解析组件-wxParse
  14. android浏览器病毒,2018安卓手机杀毒软件排行榜
  15. 正态总体均值假设检验
  16. Chrome浏览器下载东西出现卡死和未响应状态
  17. Matlab添加工具箱Toolbox的方法
  18. 论文:Pyramid Vision Transformer
  19. TCP的连接状态标识 (SYN, FIN, ACK, PSH, RST, URG)
  20. Python用海龟绘制中国国旗

热门文章

  1. 让DedeCMS的栏目页标题显示页码数
  2. keras自定义simm作为损失函数,并且实现Tensor和数组之间的转换
  3. 未来,大数据行业工资会断崖式下滑吗?
  4. 常用正则验证 :手机号、验证码、密码、邮箱等验证
  5. pfSense book之DNS解析
  6. 6818联网 8266wifi模块(附源码)
  7. C语言考试知识点汇总(实践知识点)
  8. 问题,缺陷,任务管理系统 Cynthia
  9. 成为优秀的高级开发员,重点在于……
  10. “3点钟无眠区块链”的前世今生