2024年java基础类型和包装类型的区别

java基础类型和包装类型的区别前情提要 上一篇中 通过一道常见的面试题 即 String StringBuilde StringBuffer 的区别 引申到 Java 中基本类型和包装类的相关内容 在这一篇中 我们将解决上一篇中引申出来的问题 基本类型和包装类型到底有什么区别 首先 要弄明白这两者的区别 我们就必须要知道基本数据类型和包装类到底是啥 各自都有些什么特性 请注意 除非特别注明

大家好,我是讯享网,很高兴认识大家。



前情提要

 上一篇中,通过一道常见的面试题(即:String、StringBuilder、StringBuffer的区别),引申到Java中基本类型和包装类的相关内容。在这一篇中,我们将解决上一篇中引申出来的问题——基本类型和包装类型到底有什么区别?
 首先,要弄明白这两者的区别,我们就必须要知道基本数据类型和包装类到底是啥?各自都有些什么特性?
 请注意,除非特别注明,否则本文篇中所涉及得到内容都是基于jdk1.8来说的。
 先来了解一下基本数据类型吧。

关于基本数据类型

基本数据类型到底是个啥?

在一个变量定义后,该变量指向的只能是具体的数值而非内存地址。这样的变量就属于基本数据类型。

 这一块的内容后续会再来补充,由于不是主线,暂时搁置影响也不大。

Java中基本数据类型有哪些

 在Java中,基本数据类型有8种,分别为:

布尔类型:boolean
字符类型:char
整数类型:byte、short、int、long
浮点类型:float、double

 各类型的详细信息如下表:

类型描述 名称 位数 字节数 默认值 布尔类型 boolean - java基础类型和包装类型的区别- false 字符类型 char 16 2 'u0000' 整数类型 byte 8 1 0 整数类型 short 16 2 0 整数类型 int 32 4 0 整数类型 long 64 8 0L 浮点类型 float 32 4 0f 浮点类型 double 64 8 0d

基本数据类型为什么不用new运算符?

 我们都知道new运算符可用于实例化一个对象,也就是给对象实例分配一块足够大的内存空间并返回指向该内存的引用。注意,这里所指的对象实际上是引用类型。引用对象开辟的内存空间一般是在堆中。
 相对于引用类型来说,值类型一般存放在栈上(作为成员变量的时候才会放在堆中)。因为虚拟机(根据虚拟机不同,boolean可能占用空间大小不同)对每一种基本类型的空间占用大小都是明确知晓的,所以不再需要new去开辟空间。

关于包装类

包装类的定义

 其实包装类的意义从名字就能看出一些端倪。啥叫包装,通俗了说就是把一个物体打包然后装起来。举个例子来说,比如今天我在网上买了一颗苹果,等我收到货的时候还是只有那一颗苹果吗?并不是,我拿到的是一个贴了有运单号的箱子,里面用了塑胶袋把苹果给包起来了。同理,包装类也是一样,每一个包装类里面都包了一种基本数据类型。作用也和这个例子类似,是为了让运输更方便,让苹果更安全,让我们操作更简单。

包装类的种类

 八种基本类型都有自己对应的包装类,分别为:

布尔类型:Boolean
字符类型:Character
整数类型:Byte、Short、Integer、Long
浮点类型:Float、Double

装箱和拆箱、包装类型的缓存机制

 下面我们以Integer为例,了解一下什么是装箱和拆箱,还有所谓的包装类的缓存机制到底是什么?首先,关于装箱和拆箱的概念如下:

  1. 装箱——将基本类型用各自对应的包装(引用)类型包装起来:即基本类型->包装类型;
  2. 拆箱——将包装类型转换为基本数据类型:即包装类型->基本类型;

 例如下面的代码将会发生装箱和拆箱的过程。

 
讯享网 

 编译上面的代码(javac命令),查看对应的.class文件的内容(javap命令)。

讯享网

 可以看到装箱的时候用的是Integer的valueOf方法;而拆箱的时候用的是intValue方法。在Integer中找到这两个方法。

 

 因为篇幅原因,就不一步一步的点进去看了,有兴趣的朋友自行去翻源码吧。上面的内容已经足够说明问题了,上面的描述大概说了这些东西:

  1. 该返回的是一个基于int(这个是入参,就是代码中定义的100)值的Integer的实例对象;
  2. 首先会判断入参的范围在不在[-128,127]之间。
  3. 如果不在这之间,则会调用构造方法返回一个新的Integer实例;
  4. 如果在这个范围内,则会从缓存中取一个Integer对象返回;

 Integer所谓的缓存其实是在Integer类的内部定义了一个IntegerCache的class,IntegerCache里面持有一个静态并且final修饰的缓存数组,在一开始这个数组里面就已经存入了[-128,127]之间的整型值,当你用自动装箱的方式初始化一个Integer对象并且你的整型值在这个范围内的话,会自动从这个数组中找到对应的Integer对象返回给你,而不是重新创建一个Integer对象。

 下面再来看一下拆箱中遇到的intValue方法。

讯享网

 intValue方法的描述很简单,直接返回一个int类型的值。这个int值其实就是在Integer内部包装的基本数据类型(int)。

 到此,(Integer类的)装箱、拆箱以及缓存机制差不多咱们就已经揭开那层面纱了。事实上,八大包装类型中除了浮点类型的包装类(Double和Float)并没有实现缓存技术外,其他的包装类都实现了。

  1. Byte,Short,Integer,Long这四个包装类都提供了数值[-128,127]之间的相应类型的缓存;
  2. Character提供了数值在[0,127]之间的缓存;
  3. Boolean提供了取值在{True,False}之间的缓存;
  4. 为什么浮点型不提供?因为浮点型的取值范围太广,不可能实现缓存。

基本数据类型和包装数据类型常见的面试题

(一)为什么List<int> = new List<int>();类似这样的代码会报错?
(二)包装类缓存的常见题
 
 
 
(三)Integer类的缓存区间为什么是[-128,127],为什么不把范围定义的再广一些?
(四)在Java中存在i+1<i的情况吗?

 存在,所有的基本类型都有位数的限制,比如int是32位,那么int能表示的整型范围为[-,],即:[负2的31次幂,正2的31次幂-1]。当超过这个范围时,将发生溢出,溢出后该值将变为负数。

 

 关于为什么溢出后会变为负数,大家可自己演练一下。简单提一下,32位的有符号数,第一位是符号位(为0表示正数,为1表示负数)。所以32位能表示的最大的正数是[0111 1111 1111 1111 1111 1111 1111 1111],写成16进制就是0x7FFFFFFF。再加1,低位向高位进位,相加的结果变成[1000 0000 0000 0000 0000 0000 0000 0000],表示成16进制则为0x。这个结果一看就是负数,因为最高位的符号位已经变成1了。至于为什么是-,就需要去算一下这个二进制串的补码了。


扩展区域

扩展区域主体

这是一个没有实现的扩展。


小讯
上一篇 2024-12-29 17:50
下一篇 2025-01-02 14:07

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/3238.html