`
feikiss
  • 浏览: 100297 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Java中new Integer() 和Integer.valueOf()二者效率的比较

阅读更多
最近在公司参与一个项目,项目挺大,耗时一年左右,具体业务就不说了。。。
之后在项目开发将近结束时,公司用Coverity工具对整体代码进行了检视,结果发现了N多问题,好多都是自己不注意的细节,在感叹此工具的强大的同时,问了下项目经理这个工具的价格,告知,30万$ !!! 纳尼  神马!尼玛 代码检视这块儿和findbug也差不多啊, 这也忒狠了点吧。。。

  不扯淡了,步入正题。
   在检视过程中,提到如下一个问题,就是在我们代码中用new Integer(a) 的地方,好多都提示说Ineffective way, use Integer.valueOf(int) intead. 一时感觉好奇,翻开源码查看,没有查出啥究竟,然后后来利用debug模式进入源码调试才发现,原来里面的实现也大有天地。。。
首先查看valueof(int) 方法的实现:
  /**
     * Returns a <tt>Integer</tt> instance representing the specified
     * <tt>int</tt> value.
     * If a new <tt>Integer</tt> 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.
     *
     * @param  i an <code>int</code> value.
     * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
    }

注释里面说的很清楚,“如果一个Integer的实例不是必须的,那么此方法应该优先于构造器来使用。。。” 
为什么呢?继续深入探究,进入IntegerCache类,这个是Integer类的一个内部私有类。
 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() {}
    }

至此,谜底基本解开,原来IntegerCache相当于做了一个缓存,在第一次被调用时,首先初始化生成了从-128到127共256个对象的数组,在以后凡是在这个范围内的int值都可以直接从此缓存中取,而不在再次生成Integer对象,大大提高了对象的利用率。

然后我做了一个测试类,来测试二者真正的效率区别:
	public static void testEfficiency(){
		int count = 10000000;
		long t1 = System.currentTimeMillis();
		for(int i = 0; i < count; i ++){

			int a = new Integer(i%128 *(i%2 == 0?-1:1));
			
		}
		long t2 = System.currentTimeMillis();
		for(int i = 0; i < count; i ++){
			int b = Integer.valueOf(i%128 *(i%2 == 0?-1:1));
		}
		long t3 = System.currentTimeMillis();
		System.out.println("Time of new Integer() method:"+(t2-t1)+"ms");
		System.out.println("Time of Integer.ValueOf:"+(t3-t2)+"ms");
	}

输出结果:
Time of new Integer() method:125ms
Time of Integer.ValueOf:94ms

二者似乎区别多大,不过这说明JDK虚拟机的效率比较高,
然后将这两种方式单独封装到两个方法中,利用两个程序进行调试,然后再看下javaw.exe所占的内存,区别就出来了。。。大家可以自己试一下,为了查看内存,可以将程序sleep 20s来查看, 我本机的测试结果:
new Integer方式:13 516K
Integer.valueOf方式:8 852K.
相差4664K.

实验基本到此结束,但是学习却只是一个开始,在实际项目中也可以参考此种实现方式,懒加载和缓存的思想。
分享到:
评论
5 楼 feikiss 2012-04-21  
dy110936 写道
学习了,而且还发现如果是Integer = 100这种的话,自动装箱调用的也是valueOf


Integer i = n, n 为任意数,都会调用valueOf函数的。只不过当n为-128到127的时候,对象是从cache中直接获取的,并未生成。
4 楼 dy110936 2012-04-17  
学习了,而且还发现如果是Integer = 100这种的话,自动装箱调用的也是valueOf
3 楼 woshixushigang 2012-02-01  
  共同进步嘛!
2 楼 feikiss 2012-02-01  
woshixushigang 写道
-128 到 127 共256个数,Integer y = 128;Integer z = 128; 结果 y!=z

Integer m = 127;Integer n = 127; 结果 m==n

谢谢提醒,
已经纠正过来了,的确是-128 到127, 我写成了-127到128...
测试代码如下:
public static void main(String[] args) throws IOException {
		Integer a1 = 128;
		Integer b1 = 128;
		System.out.println(a1 == b1);
		Integer a2 = -128;
		Integer b2 = -128;
		System.out.println(a2 == b2);
		Integer a3 = 127;
		Integer b3 = 127;
		System.out.println(a3 == b3);
	}

测试结果:
引用

false
true
true
1 楼 woshixushigang 2012-01-29  
-128 到 127 共256个数,Integer y = 128;Integer z = 128; 结果 y!=z

Integer m = 127;Integer n = 127; 结果 m==n

相关推荐

    Java中Integer.valueOf,parsetInt() String.valueOf的区别和结果代码解析

    Java中Integer.valueOf、parsetInt() String.valueOf的区别和结果代码解析 Java中Integer.valueOf、parsetInt()和String.valueOf都是常用的方法,但是它们之间存在着很多的区别,下面我们将通过代码来解释它们之间...

    Java Integer.ValueOf()的一些了解

    在Java中,Integer.ValueOf()方法是一个非常重要的方法,它可以将整数类型的值转换为Integer对象。下面我们就来详细了解一下这个方法的实现原理和使用方式。 首先,让我们来看一下Integer.ValueOf()方法的源码: `...

    Java Integer.valueOf()和Integer.parseInt()的区别说明

    Java 中的 Integer 类中有两个静态方法,Integer.valueOf(String s) 和 Integer.parseInt(String s),它们都可以将字符串转换为整型,但它们之间有着很大的区别。 首先,Integer.parseInt(String s) 将会返回 int ...

    Java中int和Integer的区别.doc.doc

    Java 中 int 和 Integer 的区别 在 Java 编程语言中,int 和 Integer 是两种不同的数据类型,虽然它们看起来很相似,但它们有着根本的区别。下面我们将详细探讨这两种数据类型的差异。 基本类型 vs 复杂数据类型 ...

    Java中int和Integer的区别.doc

    Java 中 int 和 Integer 的区别 Java 中的数据类型可以分为基本数据类型和复杂数据类型,int 是基本类型,而 Integer 是一个类。下面是它们之间的主要区别: 1. 数据类型 int 是基本数据类型,直接存储数值,而 ...

    JAVA-int和Integer的区别1.zip

    在Java编程语言中,`int`和`Integer`都是用于表示整数值的数据类型,但它们之间存在着显著的差异。理解这些区别对于编写高效且优化的Java代码至关重要。 首先,`int`是Java中的原始数据类型之一,它直接存储在栈...

    学习文档_JAVA中Integer和Byte转换.doc

    在Java编程语言中,Integer和Byte之间的转换是常见的操作,特别是在处理二进制数据或网络通信时。本文档主要探讨了如何在Java中实现这两种数据类型的转换,包括有符号和无符号的转换。 首先,Integer在Java中占用4...

    家庭理财系统(java+applet)130227.zip

    Integer shouru = Integer.valueOf(Moneymanager.txt1.getText()); Integer zhichu = Integer.valueOf(Moneymanager.txt2.getText()); String shijian = Moneymanager.txt3.getText(); String beizhu = ...

    【Java学习】Integer.ValueOf()引发的血案

    在Java编程语言中,`Integer.valueOf()`方法是一个关键的知识点,尤其对于理解自动装箱(autoboxing)和拆箱(unboxing)机制至关重要。在Java中,基本类型`int`与封装类`Integer`之间可以自动转换,这就是所谓的...

    Valueof_JAVA源码_java_

    总的来说,`valueOf`方法在Java编程中扮演着重要的角色,它简化了类型转换,提高了代码的可读性和效率。通过深入学习和理解这些源码,我们可以更好地掌握Java的内在工作原理,并在日常开发中更加得心应手。

    java中String类型转换方法.pdf

    int i = Integer.valueOf(hexstr, 16).intValue();` ASCII 码到字符 将 ASCII 码转换为字符可以使用以下方法: * 使用 `Character` 类:`int i = 64; String aChar = new Character((char)i).toString();` 字符...

    java中string和int型的相互转换.doc

    Java 中的 String 和 int 类型的相互转换是一个基本的数据类型转换操作,我们可以使用多种方法来实现这种转换,例如使用 `Integer.parseInt()` 方法、`Integer.valueOf()` 方法、`String.valueOf()` 方法等。...

    java中int_char_string三种类型的相互转换

    int i = Integer.valueOf(my_str).intValue(); 2. 使用 Integer.parseInt() 方法 使用 Integer.parseInt() 方法也可以将 String 转换成 int。例如: int i = Integer.parseInt(str); 二、将 String 转换成 ...

    《JAVA程序设计》期末复习题.pdf

    涵盖了JAVA语言的基础知识点,包括Java Application的主类、switch语句、变量初始化、包的声明、protected变量的访问权限、charAt()方法的使用、Integer.parseInt()和Integer.valueOf()方法的区别、事件监听器的实现...

    Mybatis Generator将tinyint映射成Integer的解决办法.pdf

    在使用MyBatis Generator生成Java DAO层代码时,可能会遇到将数据库中的tinyint类型映射成Integer类型的问题。这个问题在上述描述中得到了详细的解释。首先,我们来看一下问题的背景和原因。 在Java环境中,使用...

    java.sql.date与java.util.date.pdf

    Java.sql.Date date = new Java.sql.Date(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())); 在实际应用中,我们需要注意Java.util.Date和Java.sql.Date的...

    Springmvc : Failed to convert property value of type 'java.lang.String' to int

    使用Java的`Integer.parseInt()`或`Integer.valueOf()`方法时,可以捕获`NumberFormatException`异常,并给出友好提示。 3. **数据绑定的类型转换**:在Spring MVC中,你可以自定义类型转换器。通过实现`org.spring...

Global site tag (gtag.js) - Google Analytics