您说的那种装箱基本类型,它好用吗?

496 阅读3分钟

天天说装箱基本类型,那。。。

在Java的类型系统中,有两部分:primitive(基本类型)、reference type(引用类型)。每一个基本类型都有一个其对应的引用类型,称为装箱基本类型

基本类型 装箱基本类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

装箱基本类型用着很爽?但是有时候使用不当会引发一些bug哦~~~

有时候,我们会用到比较器,比较Integer的值。猜猜下面这段代码的结果是多少?

    public static void main(String[] args) throws InterruptedException {

        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer first, Integer second) {
                return first < second ? -1 : (first == second ? 0 : 1);
            }
        };

        Integer first = new Integer(42);
        Integer second = new Integer(42);
        int compare = comparator.compare(first, second);
        System.out.println(compare);
    }

答案:1

疑惑吗?别着急,再来一个,下面这段代码结果是啥?

    public class TestInteger {

        static Integer i;

        public static void main(String[] args) {
            if (i == 42) {
                System.out.println(true);
            }
        }
    }

答案:NullPointerException

哈哈哈哈~~~

小老弟,脑瓜子是不是嗡嗡的,想不想静静~~~


好了,开始正题。

基本类型和装箱基本类型有着三点不同:

  • 基本类型只有值,装箱基本类型有两个属性:值和同一性(我们经常说的内存地址)。

  • 基本类型只有值,装箱基本类型有值或者null

  • 基本类型比装箱基本类型更节省时间和空间。

这里面啊,还有个-128 ~ 127的问题。这个后面再说。

对于第一题,在first<second这个好理解。

运算符==用在基本类型(int)的比较上,比较的是基本类型的值。但是,如果用在装箱基本类型上(Integer),比较的是两者的内存地址firstsecond 两个变量都是new Integer()出来的,内存地址不同。所以,这个==返回的是false,现在知道最后的答案为什么是1了吧?

这里我们可以用三点不同里的第一条解释。对于第一题,可以将firstsecond拆箱再来比较。

    Comparator<Integer> comparator = new Comparator<Integer>() {
        @Override
        public int compare(Integer first, Integer second) {
            int f = first;
            int s = second;
            return f < s ? -1 : (f == s ? 0 : 1);
        }
    };

来吧,第二题!

==操作中,如果有基本类型和装箱基本类型混合操作时,装箱基本类型会自主拆箱,所以,当我们的装箱基本类型是null时,拿一个空值去拆箱,结果可想而知啊!


接下来还有一个小题目,看看这段代码有没有什么问题。

    public class TestLong {
        public static void main(String[] args) {
            Long sum = 0L;
            long s1 = System.currentTimeMillis();
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                sum += i;
            }
            System.out.println(System.currentTimeMillis() - s1);
        }
    }

结果:不会bug,但是运行速度比较慢。

原因:sum这个变量被定义成装箱基本类型,在for循环中sum不断的被装箱拆箱,导致性能明显的下降。

各位看官可以试试将sum定义成long,然后再试试这段代码的性能。

  public class TestLong {
      public static void main(String[] args) {
          long sum = 0;
          long s2 = System.currentTimeMillis();
          for (int i = 0; i < Integer.MAX_VALUE; i++) {
              sum += i;
          }
          System.out.println(System.currentTimeMillis() - s2);
      }
  }

经过小助手运行之后,结果相差非常大:

装箱基本类型耗时 : 7044

基本类型耗时 : 644

是不是很吃惊???


最后给大家留了个小思考题,很简单。

    public static void main(String[] args) {
        Integer s1 = 127, s2 = 127, t1 = 128, t2 = 128;
        
        System.out.println(s1 == s2);
        System.out.println(t1 == t2);

        Integer s3 = new Integer(127);
        Integer s4 = new Integer(127);
        Integer t3 = new Integer(128);
        Integer t4 = new Integer(128);

        System.out.println(s3 == s4);
        System.out.println(t3 == t4);
    }

提示:-128 ~ 127,又发现新知识点了吧!


推荐阅读

干啥啥不行,摸鱼第一名

听说你对git命令不熟?

20条linux命令让你在面试中脱颖而出

maven命令行不香吗?

你的简历可以这样写


长按识别下方二维码,关注摸鱼小助手,回复Python书籍,免费书籍就到手了哦!


作者个人微信二维码,来交个朋友吧!


希望在学习的路上,小助手可以助您一臂之力,一路顺风哦~~~~