zoukankan      html  css  js  c++  java
  • 深入理解Java之装箱与拆箱

    一、Java数据类型

    1、在说装箱与拆箱之前,先说一下Java的基本数据类型,Java从数据类型上可以划分为值类型引用类型,值类型是四类八种,分别是:

    • 整数型:byte̵,short̵,int̵,long
    • 浮点型:float,double
    • 字符型:char
    • 布尔型:boolean
    数据类型 内存 默认值 包装类
    byte 8位 0 Byte
    short 16位 0 short
    int 32位 0 Integer
    long 64位 0L或0l Long
    float 32位 0.0F或0.0f Float
    double 64位 0.0D或0.0d Double
    char 16位 u0000 Character
    boolean 8位 flase Boolean

    2、引用类型:

    • 数组
    • 类(class)
    • 接口(Interface)
    • 枚举(enum)

    3、值类型与引用类型的区别

    1. 从概念方面上来说:
      • 值类型:变量名指向具体的值
      • 引用类型:变量名指向数据对象的内存地址
    2. 从内存构建方面上来说:
      • 值类型:变量在声明之后,Java就会立刻分配给它内存空间
      • 引用类型:它以特殊的方式(类似C指针)指向对象实体,这类变量声明时不会分配内存,只是存储
    3. 从使用方面上来说:
      • 值类型:使用时需要赋具体值,判断时用 ” == “号
      • 引用类型:使用时可以赋null,判断时使用 equals 方法

    二、Java数据类型转换

    1、自动转换

    • 定义:程序在执行过程中“悄然”进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换

    • 优先关系:按从低到高的顺序转换。不同类型数据间的优先

      关系如下:

      • 低--------------------------------------------->高
      • byte,short,char-> int -> long -> float -> double
    • 转换规则:

      运算中,不同类型的数据先转化为同一类型,然后进行运算

      操作数1类型 操作数2类型 转换后的类型
      byte、short、char int int
      byte、short、char、int long long
      byte、short、char、int、long float float
      byte、short、char、int、long、float double double

    2、强制转换

    • 定义:强制类型转换则必须在代码中声明,转换顺序不受限制

    • 格式:在需要转型的数据前加上“( )”,然后在括号内加入需要转化的数据类型

    • 结果:精度可能会丢失,也可能更加精确

      int x;
      double y;
      
      x = (int)3.14 + (int)5.20  //精度丢失
      y = (double)x + (double)8  //精度提升
      
      输出:x = 8;y = 16.0
      

    三、Java之装箱与拆箱

    1、包装类

    • Java是面向对象语言,号称万事万物皆对象,因此,8种基本数据类型有了对应的类,这就是包装类

    2、什么是装箱与拆箱

    • 装箱:将值类型装换成引用类型的过程

    • 拆箱:将引用类型转换成值类型的过程

    • 自动装箱:

      int x = 3;
      Integer y = x;  //int --> Integer,Integer y = x <==> Integer y = Integer.valueOf(x)
      
    • 自动拆箱:

      Integer x = new Integer(5);
      int y = x;  //Integer --> int,int y = x <==> int y = x.intValue()
      

    3、装箱和拆箱是如何实现的

    • 装箱过程是通过调用包装器的valueOf方法实现的
    • 拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)

    4、注意点:

    1. 大量使用自动拆装箱会使性能降低,还会造成大量的内存消耗
    2. 在重载方法中,可能出现问题
      List<Integer> list = new ArrayList<>();
      Integer x,y,z;
      x = 1;y = 2;z = 4;
      list.add(x);list.add(y);list.add(z);
      
      list.remove(2);
      

    在上面这段代码中ArrayList.remove方法有两个重载方法,那么list.remove(2)是调用了哪个方法,remove掉的是值为2的对象,还是remove了index为2,值为4的那个对象呢?

    在这种情况下,编译器不会进行自动拆装箱,所以调用的是remove(int index),index为2值为4的这个Integer对象会被remove.

    如果要调用 remove(Object o)的方法,应该这么写 list.remove(y)

    1. 缓存值问题
    • 案例解析:

      Integer i1 = 100;
      Integer i2 = 100;
      Integer i3 = 200;
      Integer i4 = 200;
      System.out.println(i1==i2);
      System.out.println(i3==i4);
      
      Output: true false
      
    • 观察源码:

      Intteger.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类

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

      从源码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象

    • Byte、Short、Integer、Long四种包装类默认创建了数值为[-128,127]的相应类型的缓存数据,但是超出此范围仍会创建新的对象。

    • Character默认会创建[0,127]的响应类型的缓存数据

    • 两种浮点型没有实现常量池技术,在某个范围内的整型数值的个数是有限的,而浮点数却不是

      包装类 常量池 常量池范围
      Byte 存在 [-128,127]
      Short 存在 [-128,127]
      Integer 存在 [-128,127]
      Long 存在 [-128,127]
      Character 存在 [0,127]
      Float 不存在
      Double 不存在
    • 注意点:

      • 当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)
      • 对于包装器类型,equals方法并不会进行类型转换
      • 算术运算会触发装箱与拆箱过程

    文章为原创,转载请声明出处

    CSDN:https://blog.csdn.net/baidu_40188909 掘金:https://juejin.im/user/1151943919304840
  • 相关阅读:
    1219
    hdu 1280 前m大的数 和 hdu 4223 Dynamic Programming?
    codeforces Lucky Sum
    20121028
    asp.net(c#) 取得网卡mac地址
    代码使用FileUpload控件上传图片并自动生成缩略图、自动生成带文字和图片的水印图
    SQL Server日志文件总结及日志满的处理
    服务器应用程序不可用解决方案集
    如何调用存储过程,有返回值的,有参数的,存储过程中调用存储过程。(MS SQL Server)
    让网页自动刷新
  • 原文地址:https://www.cnblogs.com/kalton/p/13885721.html
Copyright © 2011-2022 走看看