好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Java Integer对象的比较方式

Java Integer对象的比较

Integer对象之间的比较要考虑到对象初始化的不同情况,初始化又涉及到对象包装器类的自动装箱特性 。

自动装箱

Integer是一种对象包装器类。对象包装器类是不可变的,也就是说,一旦完成了构造,包装在其中的值就不可以再被更改了。包装器类有一种特性,自动装箱。当需要一个Integer类型的对象时,可以对int类型的元素进行自动打包的操作。如果添加3到list中,实际调用的是下面的代码。

?

1

2

3

ArrayList<Integer> list = new ArrayList();

list.add( 3 );

list.add(Integer.valueOf( 3 ));

valueOf的源代码如下

?

1

2

3

4

5

public static Integer valueOf( int i) {

     if (i >= IntegerCache.low && i <= IntegerCache.high)

         return IntegerCache.cache[i + (-IntegerCache.low)];

     return new Integer(i);

}

其中IntegerCache定义如下

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

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 =

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

    }

JVM会维护一个Integer的数组,将值在某个范围内(默认-128~127)的对象缓存起来,在这个范围内的int会被包装到固定的对象中,valueOf会返回缓存中的对象。如果不在这个范围内,则会创建一个新的对象。注意,使用new创建的新对象是在堆中的,这一点会影响到Integer对象之间的比较结果。

自动拆箱

与自动装箱对应的,存在自动拆箱操作。当将一个Integer对象赋值给一个int值时,编译器就会插入对象拆箱指令。

?

1

2

int n = list.get(i);

int n = list.get(i).intValue();

intvalue()源代码就很简单了,返回对象的value属性

?

1

2

3

public int intValue() {

     return value;

}

Integer初始化

1.初始化Integer的时候,可以直接用一个int值赋值,实际上会自动装箱。

?

1

2

Integer n1 = 3 ;

Integer n1 = Integer.valueOf( 3 );

2.当然也可以使用new来创建Integer对象.

?

1

Integer n2 = new Integer( 3 );

Integer对象之间的比较

由于IntegerCache的存在,使用第一种方法初始化的对象,如果值的范围在-128~127之间,则相同的值会被包装的同一对象中。而用new产生的对象肯定不会在同一内存区域。

==运算符

如果使用==运算符进行比较的话,由于检测的是对象是否指向同一个内存区域,由于初始化时的不确定性,比较的结果也可能不是我们想要的。如下所示:

?

1

2

3

4

5

6

7

8

9

10

11

Integer n1 = new Integer( 47 );

Integer n2 = new Integer( 47 );

Integer n3 = 47 ;

Integer n4 = 47 ;

Integer n5 = 200 ;

Integer n6 = 200 ;

 

System.out.println(n1 == n2);   //false,两个new的对象

System.out.println(n1 == n3);   //false  n1在堆中,n3指向IntegerCache缓存(方法区中)

System.out.println(n3 == n4);   //true   都指向缓存中同一个对象

System.out.println(n5 == n6);   //false  超出缓存范围,分别是两个new出来的对象

equals

所以为了保持对象之间比较结果的一致性,同时我们进行比较的初衷应该也是比较它们之间的值,所以使用equals方法

?

1

2

3

4

5

6

public boolean equals(Object obj) {

     if (obj instanceof Integer) {

         return value == ((Integer)obj).intValue();

     }

     return false ;

}

Integer类重写了object的equals方法,调用时实际比较的是两个对象的值,和对象存储在哪里没有关系。

Integer类型变量比较问题

今天在做实验的时候,发现了一个比较奇怪的问题:两个Integer型变量用==进行比较时,有时候能成功有时候不能成功。举个例子:

代码1

?

1

2

3

4

5

6

Integer l1 = 122 ;

Integer l2 = 122 ;

if (l1 == l2)

     System.out.println( "Right" );

else

     System.out.println( "Wrong" );

  

运行这段代码时,程序会输出:Right。对于另一个例子:

代码2

?

1

2

3

4

5

6

Integer l1 = 233 ;

Integer l2 = 233 ;

if (l1 == l2)

     System.out.println( "Right" );

else

     System.out.println( "Wrong" );

  

运行这段代码时,程序会输出Wrong。但当对代码2进行修改时:

代码3

?

1

2

3

4

5

6

Integer l1 = 233 ;

int l2 = 233 ;

if (l1 == l2)

     System.out.println( "Right" );

else

     System.out.println( "Wrong" );

在运行这段代码时,程序会输出Right。如果换一种定义方式时:

代码4

?

1

2

3

4

5

6

Integer l1 = 233 ;

Integer l2 = new Integer( 233 );

if (l1 == l2)

     System.out.println( "Right" );

else

     System.out.println( "Wrong" );

运行这段代码时,程序会输出Wrong。

关于这种现象,查了下资料,总结如下

1.实际上Java中定义的Integer变量会通过Integer.valueOf()方法生成一个实例,即:

Integer l1 = 122 会被编译成 Integer l1 = Integer.valueOf(122),而关于valueOf()方法的源码:

?

1

2

3

4

5

6

public static Integer valueOf( int i) {

          assert IntegerCache.high >= 127 ;

          if (i >= IntegerCache.low && i <= IntegerCache.high)

              return IntegerCache.cache[i + (-IntegerCache.low)];

          return new Integer(i);

      }

看一下源码就会明白,对于-128到127之间的数,会进行缓存,Integer l1 = 122时,会将122进行缓存,下次再写Integer l2 = 122时,就会直接从缓存中取,就不会new了,相当于生成的为同一个对象,。所以代码1的运行结果是Right。

而对于这个范围之外的数值,valueOf()相会重新new一个对象,所以就不相等了,所以代码2的裕兴结果就是Wrong。

2.对于代码3,Integer型变量与int型变量进行比较时,实质上是把Integer类型变量拆箱成int类型,然后进行比较,相等则返回true,否则返回false。此处的拆箱调用的是intValue()方法。所以代码3的运行结果是Right。

3.对于代码4,就比较好解释了,因为new相当于重新定义了一个新的对象,即l1的引用实质是指向在堆中了,而l2实质是指向在常量池中了,所以两者是不可能相等的,故输出结果就是Wrong。

4.总之,要想比较两个Intger型变量的值最好用Integer.intValue()方法生成int型后再比较。

5.Integer型变量与int型变量之间可以直接比较,此时自动进行拆箱操作。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/bsbhenry/article/details/90743619

查看更多关于Java Integer对象的比较方式的详细内容...

  阅读:20次