详细说明基本数据类型和包装数据类型

下面是八种基本数据类型以及对应的包装类型,其他的都是引用数据类型。

数据类型包装类型占用字节
byteByte1
shortShort2
intInteger4
longLong8
floatFloat4
doubleDouble8
charCharacter2
booleanBooleantrue/false

1.为什么有基本数据类型还要有包装数据类型?使用包装类型的好处是什么?

  • 在Java中,我们知道凡是new的都会在堆空间中分配一定的内存地址,如果我么们频繁的使用Integer、Byte等等,那么会频繁的使用堆空间,因此对垃圾回收造成一定的困难,影响了使用的的效率;基本数据类型只是在栈中创建、使用、以及销毁,这样节约了空间以及效率提供。
  • 而java语言又是面向对象语言。万事万物皆对象。但是在java中,基本数据类型又不是面向对象的,因此该基本数据类型不具备面向对象的特征。为了使得基本数据类型具备面向对象的特征,那么采用将基本数据类型进行包装,使得具备面向对象的特征。为其提供基本属性以及方法,使得可以对其他对象方便使用。例如字符串转换为基本数据类型,
    1.某些方法必须使用对象作为参数,因此需要使用包装类
    2.包装类提供了更强大的方法和功能
    3方便其他对象与基本类型之间转换
    基本数据类型与包装类的对比?
类别\类型基本数据类型包装数据类型
默认值0或者falsenull
存储位置栈中堆中
使用方式直接声明直接声明或者是使用new来分配内存地址

2.包装类型与基本数据类型之间是如何转换的,以Int和Integer为例子?

  1. 分析Integer a=10;是如何进行装箱的?
    首先会在编译阶段将调用Integer的valueOf方法,将Integer a=10进行装箱操作。下面是进行装箱操作的代码以及Integer a=10;的反编译后的代码。
public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}
public static void main(java.lang.String[]);
    Code:
       0: bipush        10
       2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       5: astore_1
       6: return
}
  1. 那么int b=a;是如何将包装类型转换为int类型尼?
    首先会在编译期间调用intValue方法将拆箱操作返回包装类的具体值。以下代码是int b=a的拆箱调用的intValue方法以及反编译后的代码信息。
public int intValue() {
        return value;
 }
 public static void main(java.lang.String[]);
    Code:
       0: bipush        10
       2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       5: astore_1
       6: aload_1
       7: invokevirtual #3                  // Method java/lang/Integer.intValue:()I
      10: istore_2
      11: return
}

通过以上的分析可以看出,java在进行拆箱以及装箱过程中调用不同的方法来实现的,会在编译阶段就确定出具体的值,而不会是在运行时确定值。那么是否和String的字符串常量池类似哪?

3.在2.1的代码中看到IntegerCache表示的是什么

这个表示的是缓存类,该类中保存了包装类Integer的缓存值,那么分析可见,如果Integer a的值在-128到127时,在进行包装时,就直接获取值;如果不在这其中那么直接new Integer(a)的值

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

4。分析==以及equals方法在包装类中的使用?

首先包装类对Object类中的equals方法进行了重写,因此不想Object类中的equals方法内部使用的是==来比较。以下代码则为Integer中的equals方法.

public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

下图是分别分析a、b、c的内存分布图。

  • 当Integer a=在-128到127中时,a指向的是常量池中的值。
  • 当Integer b=500时,底层会调用ValueOf方法对其装箱,但是该值不在缓存值的范围内,因此new Integer(500)在堆中分配内存空间,所以b指向的时堆中的地址。
  • 当Integer c=new Integer(500)时,直接在堆内存中分配内存空间。所以c指向的是新的内存空间。(凡是new的都会在堆中分配内存空间)。

在这里插入图片描述
== 总结 ==
1.int和int用“= =”比较时,返回true,没有equals方法,因此不能使用equals方法
2.int和integer用= =比较时,integer会自动拆箱,所以返回true
int和new Integer()用= =比较时,integer会自动拆箱,所以返回true
3.integer和integer用= =比较时,如果值的范围在-128到127时,Integer直接从缓存中获得该值,所以直接返回true,如果不在此范围那么,那么会调用new interger()方法,所以地址值不同(返回false)
4.integer和new Integer()用= =比较时,不管Integer的值是在-128到127之间还是不在其缓存池值中,都不会分配不同的地址值,比较内存地址不同,所以为false,equals为true
5.new Integer()和new Integer()用= =比较时,比较内存地址不同(凡是new都会在堆中分配内存空间因此不会相等),所以为false,equals为true

*[注释]:

  • == 比较基本数据类型时:比较的是值
  • == 比较引用数据类型时:比较的时引用类型的地址值
  • equals方法时Object类中的方法,其引用的是==号,所以和= =用法相同,但是如果对其equals重写,那么就按照重写的规则比较。例如String、Integer类
  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值