关于Java编程,int和Integer有什么区别?

int是我们常说的整型数字,是Java的8个原始数据类型之一。Java语言虽然号称一切都是对象,但原始数据类型是例外。

Integer是int对应的包装类,它有一个int类型的字段存储数据,并且提供了基本操作,比如数学运算、int和字符串之间转换等。在Java 5中,引入了自动装箱和自动拆箱功能(boxing/unboxing),Java可以根据上下文,自动进行转换,极大地简化了相关编程。

知识扩展

1、理解自动装箱、拆箱

自动装箱与拆箱实际上算是一种“语法糖”。所谓语法糖,可简单理解为Java平台为我们自动进行了一些转换,保证不同的写法在运行时等价。因此它们是发生在编译阶段的,也就是说生成的字节码是一致的。

对于整数,javac替我们自动把装箱转换为Integer.valueOf(),把拆箱替换为Integer.intValue()。可以通过将代码编译后,再反编译加以证实。

原则上,建议避免无意中的装箱、拆箱行为,尤其是在性能敏感的场合,创建10万个Java对象和10万个整数的开销可不是一个数量级的。当然请注意,只有确定你现在所处的场合是性能敏感的,才需要考虑上述问题。毕竟大多数的代码还是以开发效率为优先的。

顺带说一下,在32位环境下,Integer对象占用内存16字节;在64位环境下则更大。

2、值缓存

就像上一讲谈到的String,Java也为Integer提供了值缓存。

Integer i1 = 1;Integer i2 = Integer.valueOf(2);Integer i3 = new Integer(3);

上述代码中第一行与第二行的写法取值使用了值缓存,而第三行的写法则没有利用值缓存。结合刚刚讲到的自动装箱、拆箱的知识,第一行代码用到的自动装箱,等价于调用了Integer.valueOf()。

不仅仅是Integer,Java也为其它包装类提供了值缓存机制,包括Boolean、Byte、Short和Character等。但与String不同的是,默认都只会将绝对值较小的值放入缓存。以Integer为例,默认情况下只会缓存-128到127之间的值。当然如果你愿意也可以通过以下JVM参数进行设置:

-XX:AutoBoxCacheMax=N

3、原始类型操作线程安全吗?

这个问题的正确答案是“线程不安全”,是否有些出乎你的意料?

原始数据类型的变量,需要使用并发相关手段才能保证线程安全。特别的是,部分比较宽的数据类型,比如long、float、double,甚至不能保证更新操作的原子性,可能出现程序读取到只更新了一半数据位的数值!关于这个话题会在这个专栏后面的并发主题详细介绍。如果有线程安全的计算需要,建议考虑使用类似AtomicInteger、AtomicLong这样线程安全的类。

int转成Integer

这个在转换的过程中会调用Integer的静态方法valueOf()方法。
源码如下:

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

这里有个IntegerCache其实就是在VM启动时,为了加快int类型到Integer的转化速度,在VM启动时就new出一些int类型与Integer的对应关系,方便直接返回Integer,而不用new。new其实是很耗时的。

注意
这里的valueOf是static的。因为,这时你想要的是Integer对象,所以只能是static的。

Integer到int的转化

这个需要调用Integer的方法intValue()。这个方法不是静态的。
源码如下:

/**
     * Returns the value of this {@code Integer} as an
     * {@code int}.
     */
    public int intValue() {
        return value;
    }

这样,当Integer转成int时,如果Integer是null的,则可能会抛空指针异常NullPointerException。

Integer integer = 1;
int i = integer;

首先会调用Integer的静态方法valueOf,然后调用integer对象的intValue方法。这时,如果integer对象是null的,在integer.intValue()时,会出现NullPointerException。

javac Test.java
javap -verbose Test
public class Test {
    public static void main(String[] args) {
        Integer integer = 1;
        int i = integer;
        System.out.println(i);
    }
}

看先反编译代码:

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: iconst_1
         1: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         4: astore_1
         5: aload_1
         6: invokevirtual #3                  // Method java/lang/Integer.intValue:()I
         9: istore_2
        10: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        13: iload_2
        14: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        17: return

一个是invokestatic、一个是invokevirtual。

如果Integer integer = null;的话:

public class Test {
    public static void main(String[] args) {
        Integer integer = null;
        int i = integer;
        System.out.println(i);
    }
}

反编译后:

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: aconst_null
         1: astore_1
         2: aload_1
         3: invokevirtual #2                  // Method java/lang/Integer.intValue:()I
         6: istore_2
         7: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        10: iload_2
        11: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
        14: return
intValue()是把Integer对象类型变成int的基础数据类型;

parseInt()是把String 变成int的基础数据类型;

Valueof()是把给定的String参数转化成Integer对象类型;(现在JDK版本支持自动装箱拆箱了。
intValue()用法与另外两个不同,比如int i = new Integer("123"),    j = i.intValue(); 相当于强制类型转换(强制类型转换事实上就是调用的这个方法)。
另外两个用法:   Integer.Valueof()  , Integer.parseInt()  用的是Interger类名。i.intValue()用的是对象i
另外,
Integer a=new Integer(1)

Integer a=Integer.valueOf(1);

两个都是得到一个Integer对象,但是Integer.valueOf的效率高。


展开阅读全文

没有更多推荐了,返回首页