JAVA基本数据类型及其对应的包装类

一、JAVA中的八种基本类型

1、数字类型(6种)

  ①byte:

    占的位数:byte数据类型占八位;

    最小值为:-128(-2^7);

    最大值为:127(2^7-1);

    默认值为:0;

    作用:byte数据类型主要用于在大型数组中节约空间,用来代替整型,因为byte类型只占八位,占用的空间只有int型的1/4;

②short:

    占的位数:short数据类型占16位;

    最小值为:-32768(-2^15);

    最大值为:32767(2^15 - 1);

    默认值为:0;

    作用:像byte类型一样节约空间,当大型数组中的元素值大小超过了byte类型却小于int类型,则用short类型存储,short类型占用的空间只有int类型的二分之一;

③int:

    占的位数:int数据类型占32位;

    最小值为:-2,147,483,648(-2^31);

    最大值为:2,147,483,647(2^31 - 1);

    默认值为:0;

    作用:一般整型变量默认为int型;

④long:

    占的位数:long数据类型占64位;

    最小值为:-9,223,372,036,854,775,808(-2^63);

    最大值为:9,223,372,036,854,775,807(2^63 -1);

    默认值为:0L;

    作用:用于存储数值超过int类型范围的值;

⑤float:

    占的位数:单精度,占32位;

    最小值为:1.4E - 45;

    最大值为:3.4028235E38;

    默认值为:0.0f;

    作用:用于存储大型浮点数组的时候可节省内存空间;

⑥double:

    占的位数:双精度,占64位;

    最小值为:4.9E-324;

    最大值为:1.7976931348623157E308;

    默认值为:0.0d;

    作用:浮点数默认类型为double类型;

注:①float和double类型不能用来表示精确的值,如货币;②为long类型的变量赋值时要在值后面加上'L',为float类型的变量赋值时要在值后面加上'f'。

数字类型取值范围的计算方法:参考博客https://blog.csdn.net/u011601165/article/details/51658910/

2、字符类型(1种)

char:

    占的位数:char类型是一个单一的 16 位 Unicode 字符;

    最小值: \u0000(即为0);

    最大值: \uffff(即为65,535);

    作用:char数据类型可以存储任何字符;

3、布尔型(1种)

boolean:

     说明:只有两个取值:true 和 false;

     默认值:false;

     作用:作为一种标志来记录 true/false 情况;

     占的位数:参考该博客https://www.jianshu.com/p/2f663dc820d0

4、其他

二、类型转换

1、转换的规则

    整型、实型(常量)、字符型数据可以混合运算。运算时,不同的数据类型先转换为同一数据类型,然后进行运算。

    数据类型转换必须满足如下规则:

    ①不能对boolean数据类型进行转换;

    ②不能把对象类型转换为不相关类对象;

    ③在把容量大的类型转换为容量下的类型时,必须用强制类型转换;

    ④转换过程中可能会导致溢出或损失精度,如:int i = 128,byte b = (byte)i;这里b = -128(溢出);

    ⑤浮点数到整数的转换是舍去小数为,并不是四舍五入,如:float f = 3.7f,int i = (int)f;这里i = 3。

2、自动类型转换

需要满足的条件:转换前的类型所占的位数小于转换后的类型所占的位数,例如:short类型占16位,就可以自动转换成32为的int型,代码如下:

3、强制类型转换

需要满足的条件:①转换的数据类型必须是兼容的;②格式:(type)value,type是要强制类型转换后的数据类型,代码如下:

4、隐含类型转换

①整数的默认类型是int型;

②浮点数默认是double型,但是定义并初始化float类型变量的时候,值后面必须跟上F或者f。

三、基本类型对应的包装类

1、概述

  虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程,基本类型的数据不具备“对象”的特性——不携带属性、没有方法可调用。 沿用它们只是为了迎合人类根深蒂固的习惯,并的确能简单、有效地进行常规数据处理。
  这种借助于非面向对象技术的做法有时也会带来不便,比如引用类型数据均继承了 Object 类的特性,要转换为 String 类型(经常有这种需要)时只要简单调用 Object 类中定义的toString()即可,而基本数据类型转换为 String 类型则要麻烦得多。为解决此类问题 ,Java为每种基本数据类型分别设计了对应的类,称之为包装类(Wrapper Classes),也有教材称为外覆类或数据类型类。

   基本数据类型对应的包装类如下图:

2、装箱和拆箱

2.1、什么是装箱和拆箱?

   前面已经提到了,JAVA为每一个基本数据类型都提供了一个包装器类,在JAVA SE5之前,如果要生成一个数值为10的Integer对象,需要这么做:

Integer integer =  new Integer(10);

而在JAVA SE5开始就提供了自动装箱功能,如果要生成数值为10的Integer对象,只需要像下面这样做就行了:

Integer integer = 10;

这样写会触发自动装箱,能直接根据数值就能创建对应的Integer对象,而不用new操作。

那么拆箱是怎么样的呢?只需要像下面这样做就行了:

Integer integer = 5;//装箱
int i = integer;//拆箱

简而言之,装箱就是基本数据类型转换为包装器类型,拆箱就是包装器类型转换基本类型。

2.2、装箱和拆箱的过程是什么?

  通过上面的介绍,知道了什么是装箱何拆箱。不过装箱和拆箱的具体过程是什么呢?其实装箱和拆箱是调用了两个函数来实现的,下面通过一段代码来说明:

public class Main {

       public static void main(String[] args) {
    	     Integer integer = 5;
    	     int i = integer;	   
       }
}

反编译这段代码生成的class文件:

从反编译的结果来看,装箱的时候调用了Integer.valueOf(int i)这个函数,拆箱的时候调用了Integer.intValue()这个函数。

总的来说,装箱的时候是调用的包装器的valueOf这个函数,拆箱的时候调用的是包装器的xxxValue这个函数(xxx是包装器对应的基本数据类型)。

2.3、装箱和拆箱关键源码分析

      通过上面的介绍,我们知道了装箱和拆箱关键在于valueOf和xxxValue这两个函数,xxxValue这个函数没有什么值得注意的,就是把包装器中的值装换为对应的基本数据类型。而valueOf这个函数在不同的包装器中,实现方法有很大的区别。

      下面,先介绍在Integer包装器类中,该方法是怎么实现的,源码如下:

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

        static {
            final int low = -128;

            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }

从上面的源码可以知道,通过valueOf创建Integer对象的时候,如果数值在区间[-128,127],那么便返回指向IntegerCache.cache数组中已经存在的对象的引用;否则创建一个新的Integer对象。简而言之,创建Integer包装器时,有一个数值在[-128,127]的缓冲池。当创建的对象数值在[-128,127]之间时,那么不需要再在内存中开辟一个空间存储,只需要将当前对象的引用指向该缓冲池中对应的对象,这样效率上得到了提高,资源也没有浪费。、

    当然,这是Integer包装器类的value函数,其他的包装器不是这样,有兴趣的可以自己查看源码,这里不一 一详解。

猜你喜欢

转载自blog.csdn.net/yangyechi/article/details/82530447