第 7 讲:谈谈 int 和 Integer 的区别、Integer 的值缓存范围

int:

int 是 Java 的 8 个原始数据类型(Primitive Types,boolean、byte 、short、char、int、float、double、long)之一。Java 语言虽然号称一切都是对象,但原始数据类型是例外。

 

Integer:

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

构建 Integer 对象的传统方式是直接调用构造器,直接 new 一个对象。我们发现大部分数据操作都是集中在有限的、较小的数值范围。在 Java 5 中新增了静态工厂方法 valueOf,在调用它的时候会利用一个缓存机制这个值默认缓存是 -128 到 127 之间。

 

1、Integer是int的包装类,int则是java的一种基本数据类型 

2、Integer变量必须实例化后才能使用,而int变量不需要 

3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值 

4、Integer的默认值是null,int的默认值是0

 

  • 关于Integer和int的应用比较 

1、由于 Integer 变量实际上是对一个Integer对象的引用,所以两个通过 new 生成的 Integer 变量永远是不相等的(因为 new 生成的是两个对象,其内存地址不同)。

Integer i = new Integer(100);

Integer j = new Integer(100);

System.out.print(i == j); //false

2、Integer 变量和 int 变量比较时,只要两个变量的值是向等的,则结果为true(自动类型提升为 int 类型——拆箱

Integer i = new Integer(100);

int j = 100;

System.out.print(i == j); //true

3、非 new 生成的 Integer 变量和 new Integer() 生成的变量比较时,结果为 false。(因为非 new 生成的 Integer 变量指向的是 java 常量池中的对象,而 new Integer() 生成的变量指向堆中新建的对象,两者在内存中的地址不同)

Integer i = new Integer(100);

Integer j = 100;

System.out.print(i == j); //false

4、对于两个非 new 生成的 Integer 对象,进行比较时,如果两个变量的值在区间 -128 到 127 之间,则比较结果为 true,如果两个变量的值不在此区间,则比较结果为 false

Integer i = 100;

Integer j = 100;

System.out.print(i == j); //true

Integer i = 128;

Integer j = 128;

System.out.print(i == j); //false

对于第 4 条的原因: 

java 在编译 Integer i = 100 ;时,会翻译成为 Integer i = Integer.valueOf(100);java对于-128到127之间的数,会进行缓存,Integer i = 127时,会将 127进行缓存,下次再写 Integer j = 127 时,就会直接从缓存中取,就不会 new 了

 

知识扩展:

理解自动装箱、拆箱:

  • 自动装箱实际上算是一种语法糖。什么是语法糖?可以简单理解为 Java 平台为我们自动进行了一些转换,保证不同的写法在运行时等价,它们发生在编译阶段,也就是生成的字节码是一致的。
  • 前面提到的整数,javac 替我们自动把装箱转换为 Integer.valueOf(),把拆箱替换为 Integer.intValue(),既然调用的是 Integer.valueOf,自然能够得到缓存好处
  • 这种缓存机制并不是只有 Integer 才有,同样存在于其他的一些包装类,比如:

1、Boolean,缓存了 true/false 对应实例,确切说,只会返回两个常量实例 Boolean.TRUE/FALSE。

2、Short,同样是缓存了 -128 到 127 之间的数值。

3、Byte,数值有限,所以全部都被缓存。

4、Character,缓存范围’\u0000’ 到 ‘\u007F’。

  • 编程实战时,原则上,建议避免无意中的装箱、拆箱行为,尤其是在性能敏感的场合,创建 10 万个 Java 对象和 10 万个整数的开销可不是一个数量级的,不管是内存使用还是处理速度,光是对象头的空间占用就已经是数量级的差距了。如:使用原始数据类型、数组甚至本地代码实现等,在性能极度敏感的场景往往具有比较大的优势,用其替换掉包装类、动态数组(如 ArrayList)等可以作为性能优化的备选项。
  • Integer、Boolean 等包装类,都被声明为“private final”,所以,它们同样是不可变类型

 

 

你可能感兴趣的:(Java36讲)