`
邓斯林玟
  • 浏览: 25580 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Integer与int解惑

阅读更多

今天在逛论坛时发现一些好的帖子,进去看了后发现有些知识点平常自己还真没有注意过,故在此转载一下,以作备忘。

 

jdk1.5引入了自动装箱(autoboxing)与自动拆箱(unboxing),这方便了集合类以及一些方法的调用,同时也使初学者对其感到非常之困惑。在此,我们来揭开其神秘的面纱。
首先,需要理清一些概念:
1、Integer是一个类,用Integer声明一个变量其是一个对象类型(或者说引用类型);int是基本类型,用int声明的变量是非对象类型,即不能在其上调用方法。
2、“==”作用于对象上的时候,其比较的是对象的引用本身的值(或者说对象的地址更容易理解),而作用于基本类型的时候比较的就是基本类型的值。

接下来看一段代码:

 

public class Test {
    public static void main(String[] args) {
        Integer i1 = 2;
        int i2 = 2;
        System.out.println(i1 == i2);
    }
}

 

在这段代码中有两个令人困惑的问题,首先是将一个基本类型的值赋值给对象的引用,即Integer i1 =2;其次是拿一个对象类型和一个基本类型比较。按理说这两种做法肯定都是有问题的,在jdk1.4(若使用的jdk版本是1.5或之后的版本中,可以使用javac -source 1.4 Test.java来编译)上,确实如此,第一个问题在编译时会报“不兼容的类型”错误,第二个问题会报“运算符 == 不能应用于 java.lang.Integer,int”的错误。

但是jdk1.5引入的自动装箱和自动拆箱,那么,必然要将其中的一种类型转换成另一种类型,究竟是将Integer对象i1转换成int基本类型呢?还是将int基本类型的i2转换成Integer对象?通过javap -c Test反编译Test.class文件就知道答案了:

 

public static void main(java.lang.String[]);
  Code:
   0:   iconst_2
   1:   invokestatic    #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   4:   astore_1
   5:   iconst_2
   6:   istore_2
   7:   getstatic       #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  aload_1
   11:  invokevirtual   #4; //Method java/lang/Integer.intValue:()I
   14:  iload_2
   15:  if_icmpne       22
   18:  iconst_1
   19:  goto    23
   22:  iconst_0
   23:  invokevirtual   #5; //Method java/io/PrintStream.println:(Z)V
   26:  return
}

 

其中,[0-4]是Integer i1 = 2的实现,我们发现,编译的字节码里调用了Integer.valueOf方法,因此Integer i1 = 2编译后就等同于Integer i1 = Integer.valueOf(2);[5,6]是int i2 = 2的实现;[7,23]是System.out.println(i1 == i2)的实现,也容易看到,里面调用了Integer.intValue()方法。因此,这个i1 == i2这两个不同类型的变量比较,在编译的时候,编译器是将其转换成相同的类型进行比较的,即将对象类型转换成基本类型,System.out.println(i1 == i2)就等同于System.out.println(i1.intValue() == i2),前面说了,“==”作用于基本类型的时候比较的就是基本类型的值,两个值都是2,所以结果是true。

另外一个令人困惑的例子就是:

 

public class Test {
    public static void main(String[] args) {
        Integer i1 = 127;
        Integer i2 = 127;
        System.out.println(i1 == i2);
  
        Integer i3 = 128;
        Integer i4 = 128;
        System.out.println(i3 == i4);
    }
}

 

运行后发现,i1==i2的结果为true,i3==i4的结果为false?这令不知原因的人头疼不已。在前面一个例子里我们已经说过,诸如Integer i1 = 127,在编译后就等同于Integer i1 = Integer.valueOf(127),既然是调用一个方法来获得对象,那么就有必要对valueOf方法一探究竟了。我们看下源码:

 

public static Integer valueOf(int i) {
    final int offset = 128;
    if (i >= -128 && i <= 127) { // must cache
        return IntegerCache.cache[i + offset];
    }
    return new Integer(i);
}

 

到此应该恍然大悟了,IntegerCache缓存了[-128,127]之间的Integer对象,如果valueOf的参数i处于这之间,就返回缓存的对象。否则就new一个新的Integer。前面已经说过,“==”作用于对象上的时候,其比较的是对象的地址,例子中的i1和i2都是从缓存中拿的,当然是同一个对象,i3和i4都是通过new Integer获得的,当然不是同一个对象了。

类似地,java.lang.Long,java.lang.Short分别缓存了[-128,127]之间的Long和Short对象,java.lang.Byte缓存了所有的对象,java.lang.Character缓存了[0,127]之间的Character对象。java缓存这些对象是为了性能优化,既然我们已经知道其缓存了这么些对象,在需要new Integer/Long/...的地方,可改用Integer/Long/Short...#valueOf方法。

本文转自Ticmyhttp://www.ticmy.com/?p=110

分享到:
评论

相关推荐

    JAVA面试题解惑系列合集

    这些类型不是对象,但在某些情况下,基本类型也有对应的包装类,比如Integer对应int、Double对应double等。 9. 继承、多态、重载和重写 继承是面向对象程序设计的核心,允许创建类的层次结构;多态允许用父类型的...

    《Java解惑》

    《Java解惑》一书揭示了Java编程中常见的困惑与陷阱,旨在帮助开发者避免这些问题,提高代码质量和效率。以下是对书中的几个关键知识点的详细解释: 1. **奇偶判断优化**: 在Java中,判断一个整数是否为奇数,...

    java解惑-语法细节介绍

    Integer intObj = 100; Long longObj = Long.valueOf(intObj.toString()); ``` 4. **对象转型**:对象转型主要用于继承关系中的子类向父类或父类向子类的转换。需要注意的是,向上转型是自动的,而向下转型则...

    java解惑(java谜题)中文版的

    1. **类型转换**:Java中的自动装箱和拆箱可能导致一些陷阱,比如Integer对象与int基本类型的比较。在处理数值时,不恰当的类型转换可能导致逻辑错误。 2. **变量作用域**:Java的局部变量、成员变量和静态变量的...

    Java面试题及解惑

    - **基本数据类型**:Java中的基本数据类型包括`byte`, `short`, `int`, `long`, `float`, `double`, `char`, `boolean`。它们是值类型,直接存储实际值。 - **String类型**:`String`不是基本数据类型,而是一个类...

    Java puzzlers(java 解惑)附源码

    例如,puzzler之一可能涉及自动装箱和拆箱,当Integer对象与int基本类型进行操作时,如果不理解它们之间的关系,可能会出现意料之外的结果。源码中可能包含这样的例子,展示了如何正确处理这种情况,避免隐式转换...

    [C语言解惑].Alan.R.Feuer.扫描版.pdf

    例如,可以使用typedef声明新的类型名称,如typedef int Integer。 C++具有丰富的操作符,包括算术操作符(如+、-、*、/、%)、关系操作符(如==、!=、&gt;、&lt;、&gt;=、)、逻辑操作符(如&&、||、!)、位操作符(如&、|...

    JAVA面试题解惑--经典面试题

    (八)Java的基本类型(内置类型)包括int、char、byte、short、long、float、double和boolean,它们都有对应的包装类,如Integer、Character等。理解它们的范围、转换规则和默认值对于编写高效代码很有帮助。 (九...

    java puzzler code

    例如,`if (true) { int x = 10; } System.out.println(x);` 在这段代码中,`x`在if语句块外部是不可见的,因此会引发编译错误。 3. **字符串操作:** - 字符串是不可变的,所以`str += "foo"`实际上是创建了一个...

    DSP开发核心教程:破解数字信号处理的密码!

    - **问题描述**:“integer conversion resulted in truncation”,数据在转换过程中丢失。 - **原因分析**:较大数值转换为较小整数类型时超出目标类型范围。 - **解决策略**: - **调整数据类型**:选择足够大...

Global site tag (gtag.js) - Google Analytics