程序员开发实例大全宝库

网站首页 > 编程文章 正文

谈谈Integer(谈谈intelcpu)

zazugpt 2024-08-17 02:10:04 编程文章 17 ℃ 0 评论

一、简介

我们都知道Integer是int的包装类。一定情况下,jdk会在两者之间自动装箱与拆箱操作。

也知道Integer是包装类,是;int是8大基本数据类型中的一种。

除此之外他们也有很多其他的不同,这里就不过多的介绍了,有兴趣的可以百度查下。

在此谈谈数据溢出、Integer缓存问题。

二、2个问题

1、取2个int数据的中间值

我们要取2个int数据的中间值,一般会像如下代码操作,一般情况没有问题的。

    public static void main(String[] args) {
        getMiddle(100, 200);// 150
    }

    // 输出2个值的中间值
    private static void getMiddle(int a, int b) {
        System.out.println((a + b) / 2);
    }

如果我的a与b都是int类型的最大值呢?结果是 -1 ? 是的,结果不是预期的结果,因为发生了数据溢出。

   public static void main(String[] args) {
        System.out.println("int型最大值是:" + Integer.MAX_VALUE + 1);// 2147483647
        getMiddle(Integer.MAX_VALUE, Integer.MAX_VALUE);// -1
    }

    // 输出2个值的中间值
    private static void getMiddle(int a, int b) {
        System.out.println((a + b) / 2);
    }

怎么解决呢?一般我们有2种解决方式,如下:

  • 使用一些小算法:

取中间值等价于 ==> a与b差的绝对值 / 2 + 最小值 ==> |( a-b)| / 2 + min

public static void main(String[] args) {
       System.out.println("int型最大值是:" + Integer.MAX_VALUE + 1);// 2147483647
       getMiddle2(Integer.MAX_VALUE, Integer.MAX_VALUE);// 2147483647
  }

   private static void getMiddle2(int a, int b) {
       // a与b差的绝对值 / 2   +   最小值
       System.out.println(Math.abs(a - b) / 2 + Math.min(a, b));
  }
  • 使用更大的数值类型(eg:long)
public static void main(String[] args) {
       System.out.println("int型最大值是:" + Integer.MAX_VALUE + 1);// 2147483647
       getMiddle3(Integer.MAX_VALUE, Integer.MAX_VALUE);// 2147483647
  }

// 会自动提升数据类型:int -> long
   private static void getMiddle3(long a, long b) {
       System.out.println((a + b) / 2);
  }

2、Integer数值比较

下方一组数值的比较以及运行结果:

    public static void main(String[] args) {
        int a = 2;
        int b = 2;
        Integer c = 2;
        Integer d = 2;
        Integer e = new Integer(2);
        Integer f = new Integer(2);

        Integer g = 128;
        Integer h = 128;
        
        /* 注意:有a或者b参与的比较,只要数值相同则结果相等,可以忽略对象这个属性,可以认为只比较数值。
                因此,a == c 是true;a == e 是true。
         */     

        System.out.println(a == b);// true
        // 因为 c 与 d 是在integer的范围中的,因此装箱后取得是同一个对象的引用
        System.out.println(c == d);// true
        // 因为 g 与 h 超过了缓存的范围,所以需要重新 new,因此是2个不同对象
        System.out.println(g == h);// false  
        // 使用new创建的对象,堆内存开辟了2个空间,是2个对象
        System.out.println(e == f);// false
        System.out.println(a == c);// true
        System.out.println(c == a);// true
        System.out.println(a == e);// true
        // c是缓存好的数据,e是new出来的,是2个不同对象
        System.out.println(c == e);// false
    }

分析原因:主要就是Integer内部有一个内部类以及装箱拆箱机制,造成如此结果。

在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法。另外IntegerCache会缓存[-128, 127]的int数据,造成对象相等。

下面是Integer的部分源代码:

    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

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

三、总结

平时在使用integer的时候,要注意一些细节,否则把错误留到生产环境就得不偿失了。我们应该留意如下2点:

  • Int / Integer 数据操作是否会产生数值溢出
  • 使用Integer做比较的时候,应当谨记Integer内部的缓存数组(范围: [-128, 127]),避免得不到期望结果

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表