我们都知道,JDK 其实给我们提供了很多很多 Java 开发者已经写好的现成的类,他们其实都可以理解成工具类,比如我们常见的集合类,日期相关的类,数学相关的类等等,有了这些工具类,你会发现它能很大程度的帮你节省时间,能很方便的实现你的需求。当然,没有这些包,你也能实现你的需求,但是你需要时间,今天我们主要是来学习一下包装类。

一、包装类介绍

1、为什么需要包装类?

我们知道 Java 语言是一个面向对象的编程语言,但是 Java 中的基本数据类型却不是面向对象的,但是我们在实际使用中经常需要将基本数据类型转换成对象,便于操作,比如,集合的操作中,这时,我们就需要将基本类型数据转化成对象,所以就出现了包装类。

2、包装类是什么呢?

包装类,顾名思义就是将什么经过包装的类,那么是将什么包装起来的呢,显然这里是将基本类型包装起来的类。包装类的作用就是将基本类型转成对象,将基本类型作为对象来处理。

Java 中我们知道,基本数据类型有8个,所以对应的包装类也是8个,包装类就是基本类型名称首字母大写。但Integer 和 Character 例外,它们显示全称,如下面表格所示:

基本数据类型对应包装类byteByteshortShortintIntegerlongLongfloatFloatdoubleDoublecharCharacterbooleanBoolean

二、包装类的继承关系

通过阅读 Java8 的 API 官方文档或者看源代码我们可以得知8个包装类的继承关系如下:

通过以上的继承关系图,我们其实可以这样记忆,包装类里面有6个与数字相关的都是继承自 Number 类,而其余两个不是与数字相关的都是默认继承 Object 类。通过看 API 官方文档,我们还可以得知这8个包装类都实现了Serializable , Comparable 接口。比如下图的 Integer 类

public final class Integer extends Number implements Comparable<Integer> {}

三、包装类的使用方法(基本操作)

接下来关于包装类的讲解我就讲Integer包装类,其他的都依此类推,用法和操作都是差不多的,只是名字不一样而已。

1、包装类的构造方法

8个包装类都有带自己对应类型参数的构造方法,其中8个包装类中除了Character还有构造方法重载,参数是String类型的。

Integer one = new Integer(666);Integer two = new Integer("666");

2、包装类的自动拆装箱

在了解自动拆装箱之前,我们得先知道什么是拆箱和装箱。其实拆装箱主要应对基本类型与包装类型的相互转换问题。

  • **装箱:**将基本类型转换成包装类型的过程叫做装箱。
  • **拆箱:**将包装类型转换成基本类型的过程叫做拆箱。

其实,在 JDK1.5 版本之前,是没有自动拆装箱的,开发人员要手动进行装拆箱:

//手动装箱,也就是将基本类型10转换为引用类型
Integer integer = new Integer(10);
//或者
Integer integer1 = Integer.valueOf(10);
//手动拆箱,也就是将引用类型转换为基本类型
int num = integer.intValue();

而在在 JDK1.5 版本之后,为了减少开发人员的工作,提供了自动装箱与自动拆箱的功能。实现了自动拆箱和自动装箱,如下方代码所示:

//自动装箱
Integer one = 1;
//自动拆箱
int two = one + 10;

其实以上两种方式本质上是一样得,只不过一个是自动实现了,一个是手动实现了。至于自动拆装箱具体怎么实现的我这里不做深入研究。

四、包装类的缓存机制

我们首先来看看以下代码,例1:

public static void main(String[] args) {Integer i1 = 100; Integer i2 = 100; Integer i3 = new Integer(100);Integer i4 = new Integer(100);System.out.println(i1 == i2);
//true  System.out.println(i1 == i3);
//false  System.out.println(i3 == i4);
//false  System.out.println(i1.equals(i2));
//true  System.out.println(i1.equals(i3));
//true  System.out.println(i3.equals(i4));
//true
}

当我们修改了值为200的时候,例2:

public static void main(String[] args) {
Integer i1 = 200; Integer i2 = 200; Integer i3 = new Integer(200); Integer i4 = new Integer(200);
System.out.println(i1 == i2);
//false  System.out.println(i1 == i3);
//false  System.out.println(i3 == i4);
//false  System.out.println(i1.equals(i2));
//true  System.out.println(i1.equals(i3));
//true  System.out.println(i3.equals(i4));
//true
}

通过上面两端代码,我们发现修改了值,第5行代码的执行结果竟然发生了改变,为什么呢?首先,我们需要明确第1行和第2行代码实际上是实现了自动装箱的过程,也就是自动实现了 Integer.valueOf 方法,其次,==比较的是地址,而 equals 比较的是值(这里的 eauals 重写了,所以比较的是具体的值),所以显然最后五行代码的执行结果没有什么疑惑的。既然==比较的是地址,例1的第5行代码为什么会是true呢,这就需要我们去了解包装类的缓存机制。

其实看Integer类的源码我们可以发现在第780行有一个私有的静态内部类,如下:

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() {
}
}

我们知道,静态的内部类是在整个 Integer 加载的时候就已经加载完成了,以上代码初始化了一个 Integer 类型的叫 cache 的数组,取值范围是[-128, 127]。缓存机制的作用就是提前实例化相应范围数值的包装类对象,只要创建处于缓存范围的对象,就使用已实例好的对象。从而避免重复创建多个相同的包装类对象,提高了使用效率。如果我们用的对象范围在[-128, 127]之内,就直接去静态区找对应的对象,如果用的对象的范围超过了这个范围,会帮我们创建一个新的 Integer 对象,其实下面的源代码就是这个意思:

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

所以 例1 代码里,i1 和i2 是100,值的范围在[-128, 127],所以直接区静态区找,所以i1和i2指向的地址是同一个,所以 i1==i2;而在例2的代码里,i1 和i2 是200,值的范围不在在[-128, 127],所以分别创建了一个新的对象,放在了堆内存里,各自指向了不同的地址,所以地址都不同了,自然 i1 不等于 i2。

通过分析源码我们可以发现,只有 double 和 float 的自动装箱代码没有使用缓存,每次都是 new 新的对象,其它的6种基本类型都使用了缓存策略。使用缓存策略是因为,缓存的这些对象都是经常使用到的(如字符、-128至127之间的数字),防止每次自动装箱都创建一次对象的实例。

五、包装类和基本数据类型的区别

  • 默认值不同

包装类的默认值是null,而基本数据类型是对应的默认值(比如整型默认值是0,浮点型默认值是0.0)

  • 存储区域不同

基本数据类型是把值保存在栈内存里,包装类是把对象放在堆中,然后通过对象的引用来调用他们

  • 传递方式不同

基本数据类型变量空间里面存储的是值,传递的也是值,一个改变,另外一个不变,而包装类属于引用数据类型,变量空间存储的是地址(引用),传递的也是引用,一个变,另外一个跟着变。

excel 日期加时间java程序里被转成浮点型_Java工具类之:包装类相关推荐

  1. java实现将阿拉伯数字转成中文大写工具类

    package com.sqds.utils;/*** <p>Title: money</p>* <p>Description: * *该类是把阿拉伯数字转换成中文 ...

  2. Java黑皮书课后题第6章:**6.24(显示当前日期和时间)程序清单2-7显示当前时间。改进这个例子,显示当前的日期和时间。程序清单6-12中的日历例子可以提供一些如何提供如何求年月日的思路

    6.24(显示当前日期和时间)程序清单2-7显示当前时间.改进这个例子,显示当前的日期和时间.程序清单6-12中的日历例子可以提供一些如何提供如何求年月日的思路 题目 题目描述 2-7显示当前时间 从 ...

  3. 小程序日期加时间筛选组件

    小程序日期加时间筛选组件 新建component->date-time-picker .wxml <picker mode="multiSelector" class= ...

  4. Java的日期与时间java.time.Duration的简介说明

    转自: Java的日期与时间java.time.Duration的简介说明 下文笔者讲述Duration类的简介说明,如下所示 Duration类简介 Duration对象:表示两个Instant间的 ...

  5. Excel日期加斜杠,日期时间戳互转

    Excel日期加斜杠,日期时间戳互转 一.日期加上斜杠,如图把20190522转成2019/05/22. 二.日期转时间戳,保证日期格式有斜杠,没有斜杠的日期不能用如下方法,需用一中方法把日期加上斜杠 ...

  6. mysql:日期加时间

    基础语法: select date_add(字段, interval 1 day); select date_add(字段, interval 1 hour); select date_add(字段, ...

  7. java中web错误返回码,关于在java程序里调用webservice报500返回码的有关问题

    关于在java程序里调用webservice报500返回码的问题 我现在写了个程序,是调用webservice的,执行后我打印返回码是500  错误信息是 java.io.IOException: S ...

  8. java程序员入门先学什么开发者工具

    学习java编程语言,那么开发工具是肯定少不了的,程序员入门基础中开发工具是一定要学会的,可以帮助开发者们提高开发效率.更优雅的写代码.由于开发者涉及的技术领域众多,以后端开发者的视角盘点平时可能用得 ...

  9. java 数字翻译成英文_Java实现将数字日期翻译成英文单词的工具类实例

    本文实例讲述了Java实现将数字日期翻译成英文单词的工具类.分享给大家供大家参考,具体如下: package com.sunyard.etp.ag.util; import java.math.Big ...

最新文章

  1. Java中的移位操作以及基本数据类型转换成字节数组【收集】
  2. Mac终端(Terminal)自定义颜色,字体,背景
  3. 阿里涉江:你真的会学习吗?从结构化思维说起
  4. Cloudflare通过集成ENS和IPFS推出通往分布式Web的网关
  5. 你看得懂的海明码校验和纠错原理
  6. 阿里38号元老:管理要轻,文化要浓
  7. Fiddler2中文乱码问题
  8. Linux基础学习记录
  9. sd卡 格式化 命令 linux,在Linux命令行上格式化SD卡、USB驱动器、闪存驱动器的方法...
  10. 基于Syntiant TinyML Board与Edge Impulse的LED语音控制(Arduino/C++)
  11. 秋招实习季,教你制作在线简历
  12. boost::python::detail::destroy_referent相关的测试程序
  13. 图文教程,Nginx+Keepalived(双机热备)介绍已经搭建高可用负载均衡环境
  14. 正式的介绍「Mutt」:命令行的邮件大师 (一文详解)
  15. 今日金融词汇---定量分析
  16. 不属于python标准库的是_Python标准库笔记(11) — Op
  17. uniapp 数据统计,数据埋点,自定义事件埋点封装
  18. RoCE Overlay
  19. ddd java repository_初探领域驱动设计(2)Repository在DDD中的应用
  20. 30多个最受用的基于XML的Flash相册教程 -- Part II

热门文章

  1. oracle全角括号忽略,Oracle中SQL查询语句日文不区分全角/半角
  2. 光伏储能容量优化MATLAB论坛,【推荐】基于需求响应的光伏微网储能系统多目标容量优化配置!...
  3. Ubuntu samba 安装与配置 实现windows和虚拟机中的Ubuntu共享文件
  4. BZOJ5475 WC2019数树(prufer+容斥原理+树形dp+多项式exp)
  5. [leetcode-117]填充每个节点的下一个右侧节点指针 II
  6. CMD终端关于pip报错,scrapy报错的一种处理方法
  7. django基础篇05-Form验证组件
  8. 如何用SQL为每一行均产生一个随机数
  9. js的5种继承方式——前端面试
  10. 将jar文件加到Maven的local repository中