java为什么要设计包装类_Java 为什么需要包装类
在 Java 的世界中,对象是一等公民,但 Java 也还是做出了妥协,出于对性能的考虑而保留了 8 种基础数据类型。
本文基于 JDK1.8
但是在某些场景下,无法直接使用基本数据类型,所以还是需要使用对象,Java 的包装类就是这样出现的。
自动装箱和拆箱
看下面的代码:
ArrayList list = new ArrayList();int i = 1;list.add(i); // 装箱;
Java 编译器会自动把基本数据类型转成对象,这个称之为装箱。 到底是怎么做到的呢?看下面的字节码:
// ...12: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;15: invokevirtual #10 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z// ...
简单解释一下 invokestatic 和 invokevirtual,这两个都是 JVM 的指令,前者表示调用 Java 的
静态方法,后者表示调用对象方法。
invokestatic 调用了 Integer.valueOf() 方法,所以装箱实际上就是调用了 Integer.valueOf() 方法。
拆箱也很简单,看下面的代码:
Integer i = 1;int i2 = 1; // 拆箱;
拆箱的字节码如下:
// ... 7: invokevirtual #2 // Method java/lang/Integer.intValue:()I // ...
同理,拆箱实际调用的是 Integer 对象方法 i.intValue()。
从上文可以看出,Java 中基本类型的装箱和拆箱实际上是编译器提供的语法糖,是在编译器层面进行处理的,编译器会将装箱和拆箱编译成调用方法的字节码。在虚拟机层,通过调用方法来实现包装类的装箱和拆箱。
Byte,Short,Long,Float,Double,Boolean,Character 与 Integer 类似。
但是需要注意,还有一个特殊的包装类 Void。 Void 是 void 的包装类,Void 不能被继承,也不能被实例化,仅仅就是一个占位符。
如果一个方法使用 void 修饰,说明方法没有返回值,如果使用 Void 修饰,则该方法只能返回 null。
public Void nullFunc() { return null; // 返回其他值会编译不通过}
Void 常用于反射中,判断一个方法的返回值是不是 void。
for (Method method : VoidDemo.class.getMethods()) { if (method.getReturnType().equals(Void.TYPE)) { // ... }}
包装类的缓存
看下面的代码:
Integer i1 = 200;Integer i2 = 200;System.out.println(i2 == i1); // falseInteger i3 = new Integer(100);Integer i4 = new Integer(100);System.out.println(i3 == i4); // falseInteger i5 = 100;Integer i6 = 100;System.out.println(i5 == i6); // true
上面的代码应该算是一道经典的面试题了。通过上文可知,装箱操作使用的是 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);}
关键实现在 IntegerCache 中,在某个范围内的数值可以直接使用已经创建好的对象。IntegerCache 是一个静态内部类,而且不能实例化,仅仅用来缓存 Integer 对象:
private static class IntegerCache { static final int low = -128; // 缓存对象的最小值,不能配置 static final int high; static final Integer cache[]; static { int h = 127; // 缓存对象的最大值可以配置,但是不能超过 Integer的最大值,不能小于 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); h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); assert IntegerCache.high >= 127; } private IntegerCache() {}}
缓存对象的默认大小范围是 -128 ~ 127,正数范围可以根据自己的需要进行调整,负数最小就是 -128,不可以调整。如果不在这个范围内,就会创建新的对象。
上面代码的结果就很清晰了,第一个结果为 false 是因为 200 超出了默认的缓存范围,因此会创建新的对象。第二个结果为 false 是因为直接使用 new 来创建对象,而没有使用缓存对象。第三个结果为 true 是因为刚好在缓存的范围内。
所以在使用 Integer 等包装类生成对象时,不要使用 new 去新建对象,而应该尽可能使用缓存的对象,而且比较两个 Integer 对象时不要使用 ==,而应该使用 equals。
其他的包装类的实现基本类似,只是在对象缓存上的实现有些不同: Byte 的范围刚好是 -128~127,所以都可以直接从缓存中获取对象。 Short 缓存范围也是 -128 ~ 127,而且不可以调整。 Long 的实现与 Short 一致。 Character 因为没有负数,所以缓存范围是 0 ~ 127,也不可以调整范围。 Boolean 的值只有 true 和 false,在类加载的时候直接创建好。 Float,Double 则没有缓存机制,因为是浮点数,可以表示无穷无尽的数,缓存的意义不大。
小心空指针
此外还需要注意的一点就是,使用包装类生成的是对象,是对象就有可能出现空指针异常,在代码中需要进行处理。
Integer integer = null;int i = integer; // NPE
java为什么要设计包装类_Java 为什么需要包装类相关推荐
- java常用类的特征_Java常用类-包装类
一. 包装类的使用 java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征 需要掌握的:基本数据类型.包装类.String三者之间的相互转换 基本数据类型 <------ ...
- java高级课程设计报告书_java高级课程设计报告模板
java高级课程设计报告模板 Java 高级课程设计报告 课程设计名称:Java高级课程设计 学 期:13-14-1 班 级:计网1231班 姓 名:黄磊 指 导 老 师:刘志生.白党强 一.课程设计 ...
- java游戏课程设计报告_java课程设计报告游戏_相关文章专题_写写帮文库
时间:2019-05-14 00:00:44 作者:admin 课 程 设 计 课程名称 Java语言课程设计 题目名称 人事管理系统的设计与实现 学生学院 应用数学学院 专业班级 学 号 学生姓名 ...
- java主窗体设计代码_java窗体设计+GUI经典代码全放送
[实例简介] java窗体设计经典代码,手把手叫你如何设计java窗体,编写应用程序. [实例截图] [核心代码] 57641e3b-d82c-4f28-bb29-35f951c1158d └── j ...
- java 包装类_Java中的包装类
Java中哪些需要包装类 它们将原始数据类型转换为对象.如果我们希望修改传递给方法的参数,则需要对象(因为基元类型是按值传递的). java.util包中的类只处理对象,因此在这种情况下包装类也有帮助 ...
- java万年历的设计总结_java万年历设计报告
内容来自用户:Van2830 JAVA大作业 目录 作业要求2项目概述2具体功能介绍3设计与实现3作业要求:62616964757a686964616fe59b9ee7ad94313334336464 ...
- java贪吃蛇设计流程_JAVA版贪食蛇(贪吃蛇)游戏的设计与实现(含录像)
JAVA版贪食蛇(贪吃蛇)游戏的设计与实现(含录像)(任务书,开题报告,外文翻译,毕业论文12000字,程序代码,MySQL数据库,答辩PPT,答辩视频录像) 摘要 "贪食蛇"游戏 ...
- java char 包装类_Java 基本类型包装类
Java基本类型包装类: 基本数据类型 基本类型包装类 byte Byte short Short int ...
- java qq课程设计报告_JAVA课程设计报告语音QQ仿真
JAVA课程设计报告语音QQ仿真 <Java 程序设计>课程设计报告 题 目: 语音 QQ 仿真 学 院:计算机科学与工程 专 业:物联网工程 学生姓名: xx 学 号: 13003701 ...
- java开发微信设计论文_java+mysql微信的烘焙公众号的设计与实现
摘要随着社会的发展人们的生活压力逐渐变大,人们日常的生活节奏也急剧加速,由此导致时间的缺少,人与人之间面对面交流的机会也越来越少.然而人类是一种群居生物,随时渴望有着他人的陪伴,这种陪伴不仅仅是物质上 ...
最新文章
- matplotlib中plot的颜色
- java怎么获取服务器文件夹,java获取远程服务器的文件夹
- 【收藏】spring boot+websocket+echarts 后台推送数据用echarts展示
- Spring和JSF集成:国际化和本地化
- [react] React中怎么检验props?
- VC6.0创建文件夹
- MooTools 1.4 源码分析 - (关于Core、Type等模块分析)
- MyEclipse7.0及JDK1.6.0的安装及配置过程(修改)
- freemarker转PDF,分页,页眉和页脚,画图
- 小程序毕设作品之微信积分商城小程序毕业设计成品(6)开题答辩PPT
- Turtle库是Python语言中一个很流行的绘制图像的函数库
- 51单片机数码管闪烁c语言,AT89C51单片机数码管闪烁问题怎么解决
- Selenium电脑上怎么下载-Selenium下载和安装图文教程[超详细]
- 2022小米红米手机最新最全MIUI刷机教程内测版到稳定版 不清除数据(线刷、卡刷)
- 范围查询-sql语句
- 基于Flink建设流批一体实时数仓
- 征途LINUX服务端脚本,征途【改版教程】-版本内脚本文件-转载于-喜欢玩网游单机站...
- 如何做到高效沟通和高效沟通的好处
- 制作商品详情页面案例
- 安装hadoop 问题记录
热门文章
- Python Bug: TypeError: a bytes-like object is required, not ‘str
- Light Field 光场以及Matlab光场工具包(LightField ToolBox)的使用说明
- Python 之pdb调试
- pyinstaller 打包错误集锦
- luogu P3193 [HNOI2008]GT考试
- 洛谷 2017.7月赛解题报告
- 61单片机程序下载一闪而过,下载完成之后没有看到实验现象。
- 不同版本操作系统和数据库的之间链接,和操作
- Ajax与jQuery异步加载数据
- 软件工程师与码农的区别