当前位置 主页 > 网站技术 > 代码类 >

    Java中值类型和引用类型的比较与问题解决

    栏目:代码类 时间:2019-12-15 15:08

    一、问题描述

    前几天因为一个需求出现了Bug。说高级点也挺高级,说白点也很简单。其实也就是一个很简单的Java基础入门时候的值类型和引用类型的区别。只是开发的时候由于自己的问题,导致小问题的出现。还好突然想起来以前看过一篇对于该问题讲解的博客,才能快速定位问题的位置。防止下次再犯,顺便也就把这个当做笔记记录下来,放入自己的Bug集中。

    二、值类型和引用类型的比较

    这个大家应该都是没问题的,很简单。值类型比较是比较值,引用类型是比较地址。对于正常的操作来说,比较值类型我们可以直接使用 == ,引用类型就使用equals来做比较就不会出现问题。

    引用类型

    /**
      * 测试Integer
      */
     public static void test_Integer(){
      Integer number_01 = 10;
      Integer number_02 = 10;
      System.out.println(number_01.equals(number_02));
     }

    上面的测试结果很明显是true,绝对没有问题的。

      

    值类型

    /**
      * 测试int
      */
     public static void test_Int(){
      int number_01 = 10;
      int number_02 = 10;
      System.out.println(number_01 == number_02);
     }

    上面的测试结果很明显是true,绝对没有问题的。

    三、问题

    但是问题就出现在,开发的使用为了防止出现为null的时候会被系统使用0来代替,所以就使用了Integer类型来做操作,并且在比较的时候用了 == 。这就很尴尬了,开始自测完全没出现问题,因为没到达记录数。很开心,把代码提交下班,妥妥的。但是尴尬的事情来了,测试报告出现在了邮箱里面了。

    初始没问题的情况

    /**
      * 测试Integer
      */
     public static void test_Integer(){
      Integer number_001 = 10;
      Integer number_002 = 10;
      System.out.println(number_001 == number_002);
     }

    结果:

    当记录超过一定数的时候,出现问题

    /**
      * 测试Integer
      */
     public static void test_Integer(){
      Integer number_001 = 128;
      Integer number_002 = 128;
      System.out.println(number_001 == number_002);
     }

    结果:

    四、解决

    后面一想,很快确定问题了。是自己的马虎,偷懒使用了 == ,造成这次问题的出现,当改为equals就可以妥妥的回家了。开始自测没问题主要还是因为Integer 的缓存搞的事情。扒拉到Integer的源码,发现里面用了缓存机制,对-128~127的值做了缓存,如果在这个值区间内使用==来做比较的话,比较的就是值了,所以才造成开始以为没问题,后面运行了一段时间后就出现问题了。当不在值区间内就必须使用equals来完成比较。

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