`
hz_chenwenbiao
  • 浏览: 994617 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

C#之int挑战Java之Integer(转)

阅读更多

可能有些图会看不到,可以到转载处去阅读:http://kb.cnblogs.com/page/79961/

 

  本文涉及到一些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文件:

1

  通过仔细阅读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对象。

  一切真相大白。 

分享到:
评论

相关推荐

    C#-DES_SAME_JAVA-DES.zip

    本代码是C#方法,通过开源C#BouncyCastle加密组件进行DES加解密。和JAVA DES加解密互通。JAVA方法如下: public static String desEncrypt(String source, String desKey) throws Exception { try { // 从原始...

    在一小时内学会 C#(txt版本)

    如果熟悉 Java 语言,Java 的编程结构、打包和垃圾回收的概念肯定对你快速学习 C# 大有帮助。所以我在讨论 C# 语言构造的时候会假设你知道 C++。 本文通过一系列例程以简短但全面的方式讨论了 C# 语言构造和特性,...

    JEvents:一个模拟 C# 委托和事件的非注解驱动的 java 事件处理框架

    一个模拟 C# 委托和事件的非注解驱动的 Java 事件处理框架。 发布 Jar 下载 如何使用 第一步:为事件创建一个接口(以下只是一个例子,可以是任何接口) public interface IListener { public void ...

    jyield:java continuations 支持类似于 c# yield

    产量当心:这个项目目前没有得到积极维护。...public class Sample { @Continuable public static Iterable&lt; Integer&gt; power ( int number , int exponent ) { int counter = 0 ; int result = 1 ;

    java面试题

    答:int是java的原始数据类型,Integer是java为int提供的封装类,java为每个原始数据类型都提供了封装类。 String和StringBuffer的区别? 答:String是不可变的对象,每次对String类型进行改变都相当于产生了一个新...

    delphi与java 加密解密 DES/CBC/PKCS5Padding

    最近做一个接口,与JAVA的关于DES/CBC/PKCS5Padding 互相解密。在网上找了很多资料,摸索了3天才摸索出来。同样的明文,用JAVA加密的密文死活都跟用DELPHI加密的不相等,有时候少于8个字符的就正常,多了8个字符的就...

    sesvc.exe 阿萨德

    C# Node.Js 一文让你彻底理解 Java HashMap 和 ConcurrentHashMap 2018-07-25 分类:JAVA开发、编程开发、首页精华0人评论 来源:crossoverjie.top 分享到:更多0 前言 Map 这样的 Key Value 在软件开发中是非常...

    INTERFACEDE-DEGISKENLER

    数据类型是原始数据还是对象源数据(例如int / Integer)都没有关系。 如果我们将Inerface视为分析师, 这是一个特殊的类,它仅说明要做的事情,不会干扰内容。 在其中定义全局变量会导致过程干扰,降低代码质量...

    FMLDATA的源码

    (四)读写FMLDATA文件 了解了文件结构后,可以用各种语言如C/C++、C#、VB、VBA、JAVA、SAS、…………………………等读写文件。 1、用VBA将EXCEL工作表数据写入FMLDATA文件: Sub exceldata2fmldata() '将EXCEL工作...

Global site tag (gtag.js) - Google Analytics