C#之int挑战Java之Integer

  本文涉及到一些JVM原理和Java的字节码指令,推荐感兴趣的读者阅读一本有关JVM的经典书籍《深入Java虚拟机(第2版)》,将它与我在《.NET 4.0面向对象编程漫谈》中介绍的CLR原理与IL汇编指令作个对比,相信读者会有一定的启发。而仔细对比两个类似事物的异同,是很有效的学习方法之一。

  今后我还将在个人博客上放出其他的文章,希望能帮助书的读者开拓视野,启发思考,大家一起探讨技术的奥秘。

  本文所述之内容仅代表个人之理解,任何疏漏及错误请直接回贴指出。

  1 奇特的程序输出

  前段时间,一个学生给我看了一段“非常诡异”的Java代码:

public class TestInteger {

public static void main(String[] args){

Integer v1=100;

Integer v2=100;

System.out.println(v1==v2); //输出:true

Integer w1=200;

Integer w2=200;

System.out.println(w1==w2); //输出:false

}

}

  让这个学生最困惑的是,为什么这些如此相似的代码会有这样令人意外的输出?

  我平时多使用C#,Java用得不多,初看到这段代码的输出,我也同样非常奇怪:怎么会这样呢?100和200这两个整型数值对Integer这个类有本质上的差别吗?

  为了弄明白出现上述现象的底层原因,我使用javap工具反汇编了Java编译器生成的.class文件:

  通过仔细阅读Java编译器生的字节码,我发现以下给Integer变量赋值的语句:

  Integer v1=100;

  实际上调用的是Integer.valueOf方法。

  而完成两个Integer变量比较的以下语句:

  System.Console.WriteLine(v1 == v2);

  实际生成的是if_acmpne指令。其中的a代表“address”,cmp代表“Compare”,ne代表“not equal”。

  这条指令的含义是:比较Java方法栈中的两个操作数(即v1与v2),看看它们是不是指向堆中的同一个对象。

  当给v1和v2赋值100时,它们将引用同一个Integer对象。

  那为什么当值改为200时,w1和w2就“翻脸了”,分别引用不同的Integer对象?

  秘密就在于Integer.valueOf方法。幸运的是,Java的类库是开源的,所以我们可以毫不费力地看到相关的源代码:

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对象的cache数组来缓存Integer对象,其代码如下:

private static class IntegerCache {

static final Integer cache[];

//……

}

  再仔细看看IntegerCache内部的代码,会看到它使用静态初始化块在cache数组中保存了[-128,127]区间内的一共256个Integer对象。

  当给Integer变量直接赋整数值时,如果这个数值位于[-128,127]内,JVM(Java Virtual Machine)就直接使用cache中缓存的Integer对象,否则,JVM会重新创建一个Integer对象。

  一切真相大白。 

时间: 2024-09-30 12:42:13

C#之int挑战Java之Integer的相关文章

一起谈.NET技术,C#之int挑战Java之Integer

本文涉及到一些JVM原理和Java的字节码指令,推荐感兴趣的读者阅读一本有关JVM的经典书籍<深入Java虚拟机(第2版)>,将它与我在<.NET 4.0面向对象编程漫谈>中介绍的CLR原理与IL汇编指令作个对比,相信读者会有一定的启发.而仔细对比两个类似事物的异同,是很有效的学习方法之一. 今后我还将在个人博客上放出其他的文章,希望能帮助书的读者开拓视野,启发思考,大家一起探讨技术的奥秘. 本文所述之内容仅代表个人之理解,任何疏漏及错误请直接回贴指出. 1 奇特的程序输出 前段时

java中 Integer a=5;和Integer a = new Integer(5);的区别?请高手赐教。

问题描述 java中 Integer a=5;和Integer a = new Integer(5);的区别?请高手赐教. /*首先要知道的常识:1.关系操作符==:计算""操作数""的 值 之间的关系,结果为true或者false;这操作数指的是所有的基本数据类型以及所有对象;2.equals():是Object类中的方法,equals()作用和==相同,但是不适用于基本数据类型:3.自己定义的类可以覆盖Object类中的equals(); *///下面来看一个例

no suitable HttpMessageConverter found for request type [java.lang.Integer]

今天在使用Spring Template的时候遇到了这个异常: no suitable HttpMessageConverter found for request type [java.lang.Integer] Google了一下然后在stackoverflow上面找到了解决方案: I have a method in Spring rest service. @RequestMapping(value = "test/process", method = RequestMetho

java中Integer包装类的详细讲解(java二进制操作,所有进制转换)

程序员都很懒,你懂的! 今天为大家分享的是Integer这个包装类.在现实开发中,我们往往需要操作Integer,或者各种进制的转换等等.我今天就为大家详细讲解一下Integer的使用吧.看代码: package com.herman.test; public class IntegerTest { public static void main(String[] args) { System.out.println("Integer中的常量***************************

java.lang.Integer.toHexString(b[n] &amp;amp; 0XFF)中0XFF使用

byte[] b = {5,2,20,108}; String stmp = java.lang.Integer.toHexString(b[n] & 0XFF)   在32位的电脑中数字都是以32格式存放的,如果是一个byte(8位)类型的数字,他的高24位里面都是随机数字,低8位 才是实际的数据.java.lang.Integer.toHexString() 方法的参数是int(32位)类型,如果输入一个byte(8位)类型的数字,这个 方法会把这个数字的高24为也看作有效位,这就必然导致错

Java基础 Integer类型比较疑惑

问题描述 Java基础 Integer类型比较疑惑 求解释,为何输出都是 true ? 感谢 public static void main(String[] args) { Integer int1 = new Integer(1); Integer int2 = new Integer(1); System.out.println(int1 >= int2); //true System.out.println(int1 <= int2); //true } 解决方案 int1 和 int

Ljava.lang.Integer;cannot be cast to java.lang.Integer:JPA查询参数设置请教

问题描述 我在使用JPA时,使用如下查询语句:Query query = em.createQuery(select bean from Content bean where bean.departmentId in (:departmentIds));然后设置参数:query.setParameter("departmentIds", departmentIds);这个departmentIds是Integer[]型的.程序运行时:提示 [Ljava.lang.Integer;can

java.lang.Integer cannot be cast to

问题描述 public List<Materials> findAllMaterialsByAppid(Integer appid) {String hql1 = "select medid from Materials where appid = ? and pid = 0";List<Materials> list = this.hibernateTemplate.find(hql1, appid);if (list != null && l

hibernate annoation (四 lob)

hiberante sql映射对应 Java数据类型 Hibernate数据类型 标准SQL数据类型 (PS:对于不同的DB可能有所差异) byte.java.lang.Byte byte TINYINT short.java.lang.Short short SMALLINT int.java.lang.Integer integer INGEGER long.java.lang.Long long BIGINT float.java.lang.Float float FLOAT double