zoukankan      html  css  js  c++  java
  • Integer类型与享元模式

    工程中某方法返回一个Integer:virusRes
    另有:某枚举类:
     1 public enum VirusCheckRes {
     2     
     3     UNKNOW(0), SAFE(1), HIGH_RISK(2), MEDIUM_RISK(3), LOW_RISK(4);
     4     
     5     private Integer status;
     6     private VirusCheckRes(Integer status){
     7         this.status = status;
     8     }
     9     public Integer getStatus() {
    10         return this.status;
    11     }
    12     public void setStatus(Integer status) {
    13         this.status = status;
    14     }
    15         
    16 }
    View Code

    在做如下判断时:

    if (VirusCheckRes.SAFE.getStatus() == virusRes) 

    当virusRes和SAFE都=1 时,结果返回的false
     
    老生常谈的问题,即便是Integer这样的基础变量包装类,判断等于(==)的时候,也是比较对象的地址,而非对象的值,如果比较对象的值,请出门左拐用equals。
    but!(Integer类源码)
        public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
        }
    View Code

    即便是equals,也是比较的intValue(),所以为了代码看起来更易读,还是直接使用VirusCheckRes.SAFE.getStatus().intValue() == virusRes.intValue(),比较好。
     
    既然聊到了Integer,就在多扯两句,Integer与享元模式:
    采用http://blog.csdn.net/gaoxueyi551/article/details/9091349中的例子:
    public class Test {
    
     /**
      * @param args
      */
     public static void main(String[] args) {
      // TODO Auto-generated method stub
      
      Integer a1 = new Integer(4);
      Integer a2 = new Integer(4);
      System.out.println(a1 == a2); //false
      
      
      Integer i1 = 13;
      Integer i2 = 13;
      System.out.println(i1 == i2); //true
      
      
      
      Integer i3 = 128;
      Integer i4 = 128;
      
      System.out.println(i3 == i4); //false
      
      Integer i5 = Integer.valueOf(3);
      Integer i6 = Integer.valueOf(3);
      System.out.println(i5 == i6); //true
      
      Integer i7 = Integer.valueOf(128);
      Integer i8 = Integer.valueOf(128);
      System.out.println(i7 == i8); //false
     
    
     }
    
    }
    View Code

    a1==a2  -> false可以理解,跟我的错误一样

    i1==i2    -> true 就有点意思了

    接下来

    i3 = i4     -> false(与i1=i2有什么区别?)

    i5 == i6   -> true 什么鬼

    i7==i8     -> false

    根据a1 != a2 ,i1 == i2, i5 == i6,可以看出,自动装箱用的应该是valueOf方法,而非构造方法,从反编译得到的字节码中也可以证明这点

    源码为:

    public class Main {
        public static void main(String[] args) {
             
            Integer i = 10;
            int n = i;
        }
    }

    反编译的字节码

    同样可以看出,拆箱时,用的是intValue方法
     


    那么为什么3还好好的,128经过装箱之后就返回的false呢?
    看了Integer的源码真的感觉jdk的强大啊,这里用到了设计模式中的享元模式:
     
    上文书说道装箱用到了i1==i2和i5 == i6都返回了true,而且又说道这四个变量其实都用到了相同的方法valueOf,那么就来看看valueOf
        public static Integer valueOf(int i) {
            if(i >= -128 && i <= IntegerCache.high)
                return IntegerCache.cache[i + 128];
            else
                return new Integer(i);
        }

    IntegerCache.cache[] 是什么鬼?
    818
        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() {}
        }
    View Code

    (integerCacheHighPropValue貌似可以通过JVM配置)
     
        // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
        private static String integerCacheHighPropValue;

    从代码中可以看出,IntegerCache是Integer中的内部类,里面定义了两个属性,high,cache,其中high在static块中给出了赋值,如果配置integerCacheHighPropValue的话,默认的high是127,low=-128

    现在再回过头看
        public static Integer valueOf(int i) {
            if(i >= -128 && i <= IntegerCache.high)
                return IntegerCache.cache[i + 128];
            else
                return new Integer(i);
        }

    如果i属于[-128,127],则返回cache[i+128],cache如代码所示,是IntegerCache的一个静态数组,是保存一份
    因此,当自动装箱的i在[-128,127]范围内,则不生成新的Integer,而是共享了一个Integer对象。(享元模式)
    超出该范围的Integer才真正的new出了Integer对象。
     
    其他的如Long,Double,Float,Boolean等类型,不再啰嗦。
    以上。
     
     
     参考资料:
    http://blog.csdn.net/gaoxueyi551/article/details/9091349
    http://www.cnblogs.com/dolphin0520/p/3780005.html
    http://1006836709.iteye.com/blog/1714378
  • 相关阅读:
    vscode 远程编辑文件
    neo4j
    sqlite3-python
    pypdf2:下载Americanlife网页生成pdf合并pdf并添加书签
    thisamericanlife 百度api及腾讯翻译-正式版
    为微信二维码添加gif动态背景
    python- www.thisamericanlife.org转pdf
    python爬虫添加请求头
    Python-redis
    k8s权威指南-从xx到oo的实践全接触
  • 原文地址:https://www.cnblogs.com/huntfor/p/4668558.html
Copyright © 2011-2022 走看看